如何在 SpringBoot + SpringSecurity 应用程序中配置 CORS?

我使用 Spring 启动,支持 Spring 安全性和 Cors。

如果我执行以下代码

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
if xmlhttp.readyState is 4
console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:a'
do xmlhttp.send

我得到的结果

200

如果我使用错误的凭据进行测试,比如

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
if xmlhttp.readyState is 4
console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:aa'
do xmlhttp.send

而不是得到401(这是春季安全性中错误身份验证的标准代码)

0

浏览器通知如下:

接通 http://localhost:5000/api/token

XMLHttpRequest 无法加载 http://localhost:5000。请求的资源上没有“访问控制-允许-起源”标头。因此,不允许访问起源“ http://localhost:3000”。反应 HTTP状态码为401。

我正在开发前端代码,需要有用的 http 状态代码从服务器响应来处理这种情况。我需要比0更有用的东西。响应主体也是空的。我不知道如果我的配置是错误的,或者它是一个软件错误,我也不知道在哪里,如果它是铬(使用 arch linux)或春天安全。

我的 Spring 配置是:

@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}


@RestController
@RequestMapping("api")
public class Controller {
@RequestMapping("token")
@CrossOrigin
Map<String, String> token(HttpSession session) {
return Collections.singletonMap("token", session.getId());
}
}


@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.anyRequest().authenticated()
.and().httpBasic();
}
}

如果我使用 curl 进行测试,那么一切都很完美,我认为这是因为不需要 CORS 支持,但是我尝试使用 OPTION 请求模拟 CORS,结果也是可以的。

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTpha"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTpha
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin,Accept,X-Requested-    With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
< x-auth-token: 58e4cca9-7719-46c8-9180-2fc16aec8dff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:15:44 GMT
<
* Connection #0 to host localhost left intact
{"token":"58e4cca9-7719-46c8-9180-2fc16aec8dff"}

以及错误的证书:

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTp"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTp
>
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< WWW-Authenticate: Basic realm="Realm"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:16:15 GMT
<
* Connection #0 to host localhost left intact
{"timestamp":1462119375041,"status":401,"error":"Unauthorized","message":"Failed to decode basic authentication token","path":"/api/token"}

编辑: 为了避免误解,我使用了1.3.3 SpringBoot。 这篇博文写道:

CORS 支持将在即将发布的 Spring Boot 1.3版本中提供,并且在1.3.0.BUILD-SNAPSHOT 构建中已经提供。

在 Spring Boot 应用程序中使用带有@CrossOrigin 注释的控制器方法 CORS 配置不需要任何特定的配置。

全局 CORS 配置可以通过使用定制的 addCorsMaps (CorsRegistry)方法注册 WebMvcConfigurerbean 来定义:

我添加了以下代码以启用全局 cors 支持。实际上我以前试过,但结果是一样的。我最近又试了一次,结果还是一样。

@Configuration
public class MyConfiguration {


@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}

但是,认为问题来自授权过程之间的重定向是一个有趣的想法。我如何改变重定向到任何资源,以避免这种冲突?

编辑:

我想我快找到解决办法了。我已经测试了我的 nodejs 服务器,它通过添加 访问-控制-允许-来源: * 所有的要求。

就像 Stefan Isele 已经提到的那样,似乎春季安全重定向或不添加 CORS 头,所以这就是为什么请求似乎被破坏了。因此,当 Spring 安全性检查身份验证时,它必须添加适当的头。

有人知道怎么做吗?

编辑:

我找到了一个变通方案,看起来很难看。我已经开始了一个针对春季启动的 github 问题,在这里我描述了解决方案: https://github.com/spring-projects/spring-boot/issues/5834

369975 次浏览

Cross origin protection is a feature of the browser. Curl does not care for CORS, as you presumed. That explains why your curls are successful, while the browser requests are not.

If you send the browser request with the wrong credentials, spring will try to forward the client to a login page. This response (off the login page) does not contain the header 'Access-Control-Allow-Origin' and the browser reacts as you describe.

You must make spring to include the haeder for this login response, and may be for other response, like error pages etc.

This can be done like this :

    @Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {


@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}

This is copied from cors-support-in-spring-framework

I would start by adding cors mapping for all resources with :

registry.addMapping("/**")

and also allowing all methods headers.. Once it works you may start to reduce that again to the needed minimum.

Please note, that the CORS configuration changes with Release 4.2.

If this does not solve your issues, post the response you get from the failed ajax request.

Spring Security can now leverage Spring MVC CORS support described in this blog post I wrote.

To make it work, you need to explicitly enable CORS support at Spring Security level as following, otherwise CORS enabled requests may be blocked by Spring Security before reaching Spring MVC.

If you are using controller level @CrossOrigin annotations, you just have to enable Spring Security CORS support and it will leverage Spring MVC configuration:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}

If you prefer using CORS global configuration, you can declare a CorsConfigurationSource bean as following:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}


@Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}

This approach supersedes the filter-based approach previously recommended.

You can find more details in the dedicated CORS section of Spring Security documentation.

If you are using Spring Security, you can do the following to ensure that CORS requests are handled first:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsConfigurationSource
.cors().and()
...
}


@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}

See Spring 4.2.x CORS for more information.

Without Spring Security this will work:

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS");
}
};
}

For properties configuration

# ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties)
endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported.
endpoints.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
endpoints.cors.allowed-methods=GET # Comma-separated list of methods to allow. '*' allows all methods.
endpoints.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
endpoints.cors.exposed-headers= # Comma-separated list of headers to include in a response.
endpoints.cors.max-age=1800 # How long, in seconds, the response from a pre-flight request can be cached by clients.

Found an easy solution for Spring-Boot, Spring-Security and Java-based config:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
return new CorsConfiguration().applyPermitDefaultValues();
}
});
}
}

If you use JDK 8+, there is a one line lambda solution:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
}

I solved this problem by:

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;


@Configuration
public class CORSFilter extends CorsFilter {


public CORSFilter(CorsConfigurationSource source) {
super((CorsConfigurationSource) source);
}


@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {


response.addHeader("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
if (response.getHeader("Access-Control-Allow-Origin") == null)
response.addHeader("Access-Control-Allow-Origin", "*");
filterChain.doFilter(request, response);
}


}

and:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;


@Configuration
public class RestConfig {


@Bean
public CORSFilter corsFilter() {
CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://localhost:4200");
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.POST);
((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", config);
return new CORSFilter(source);
}
}

I had the same problem on a methood that returns the status of the server. The application is deployed on multiple servers. So the easiest I found is to add

@CrossOrigin(origins = "*")
@RequestMapping(value="/schedulerActive")
public String isSchedulerActive(){
//code goes here
}

This method is not secure but you can add allowCredentials for that.

I solved this problem by: `

@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers","Access-Control-Allow-Origin","Access-Control-Request-Method", "Access-Control-Request-Headers","Origin","Cache-Control", "Content-Type", "Authorization"));
configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}

`

Cors can be a pain in the ass, but with this simple code you are Cors ONLY!!!! to to specified method

@CrossOrigin(origins="*")// in this line add your url and thats is all for spring boot side
@GetMapping("/some")
public String index() {
return "pawned cors!!!!";
}

Like a charm in spring boot 2.0.2

I was having major problems with Axios, Spring Boot and Spring Security with authentication.

Please note the version of Spring Boot and the Spring Security you are using matters.

Spring Boot: 1.5.10 Spring: 4.3.14 Spring Security 4.2.4

To resolve this issue using Annotation Based Java Configuration I created the following class:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {


auth.inMemoryAuthentication()
.withUser("youruser").password("yourpassword")
.authorities("ROLE_USER");
}


@Override
protected void configure(HttpSecurity http) throws Exception {


http.cors().and().
authorizeRequests()
.requestMatchers(CorsUtils:: isPreFlightRequest).permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.realmName("Biometrix");


http.csrf().disable();


}


@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Authorization"));
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}

One of the major gotchas with Axios is that when your API requires authentication it sends an Authorization header with the OPTIONS request. If you do not include Authorization in the allowed headers configuration setting our OPTIONS request (aka PreFlight request) will fail and Axios will report an error.

As you can see with a couple of simple and properly placed settings CORS configuration with SpringBoot is pretty easy.

Kotlin solution

...
http.cors().configurationSource {
CorsConfiguration().applyPermitDefaultValues()
}
...

After much searching for the error coming from javascript CORS, the only elegant solution I found for this case was configuring the cors of Spring's own class org.springframework.web.cors.CorsConfiguration.CorsConfiguration()

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
}

Solution for Webflux (Reactive) Spring Boot, since Google shows this as one of the top results when searching with 'Reactive' for this same problem. Using Spring boot version 2.2.2

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.cors().and().build();
}


@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();


config.applyPermitDefaultValues();


config.addAllowedHeader("Authorization");


UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);


return new CorsWebFilter(source);
}

For a full example, with the setup that works with a custom authentication manager (in my case JWT authentication). See here https://gist.github.com/FiredLight/d973968cbd837048987ab2385ba6b38f

You can finish this with only a Single Class, Just add this on your class path.

This one is enough for Spring Boot, Spring Security, nothing else. :

        @Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCorsFilterConfig implements Filter {


@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, enctype");
response.setHeader("Access-Control-Max-Age", "3600");
if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}


@Override
public void destroy() {
}


@Override
public void init(FilterConfig config) throws ServletException {
}




}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
}
};
}
// https://docs.spring.io/spring-boot/docs/2.4.2/reference/htmlsingle/#boot-features-cors
@Configuration
public class MyConfiguration {


@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
}
};
}
}

If using Spring Security, set additional:

// https://docs.spring.io/spring-security/site/docs/5.4.2/reference/html5/#cors
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(final HttpSecurity http) throws Exception {
// ...


// if Spring MVC is on classpath and no CorsConfigurationSource is provided,
// Spring Security will use CORS configuration provided to Spring MVC
http.cors(Customizer.withDefaults());
}
}

How to Solve CORS on Spring Boot 2.3+

Summary

If you are facing this CORS issue, don't worry. It's a common issue for every backend developer when they try to integrate with front-end microservices for the first-time. It's some sort of security policy that browsers are strictly applying for the safety of the users and that's why you are not facing it when you tried your API via Postman/Swagger or cURL.

Solutions

  • Client-Side Bypass (Dev Only)

Following solutions are just only for development purposes, you absolutely need to solve this CORS issue permanently for your production environment. You can use the following browser extensions to bypass browser policies for CORS error but don't get surprised if they didn't work properly.

  1. CORS Unblock Firefox - Chrome
  2. CORS Everywhere Firefox
  • Production Solutions

There are different ways to configure CORS policies on the application and it's completely based on your deployment architecture. For example, if your application is going to be exposed through Reverse Proxies (like Nginx), API Gateways (Kong), Service Mesh Sidecar Proxies (i.e Envoy), Kubernetes NGINX Ingress, and so forth, the Best Practice is to handle the CORS configuration on the Edge layer because sometimes they don't consider lower layers headers and they overwrite them and you will still receive CORS errors from the Browser. I have listed useful links for the configuration of edge layers in the following

But, If you are going to deploy and expose your APIs through SprintBoot's built-in web server, you can use the instructions in the next.

Instructions to Enable CORS Globally - Spring Boot Application

If you don't have any implementation for WebSecurityConfig, Just easily do the following steps:

  1. Add the following dependency [spring-boot-starter-security] to your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. Create a new class in your config package that extends WebSecurityConfig (i.e 'SecurityConfig')
  2. Put the following codes into the created file:
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;


import java.util.List;


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{




@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
corsConfiguration.setAllowedOrigins(List.of("*"));
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setExposedHeaders(List.of("Authorization"));
        

// You can customize the following part based on your project, it's only a sample
http.authorizeRequests().antMatchers("/**").permitAll().anyRequest()
.authenticated().and().csrf().disable().cors().configurationSource(request -> corsConfiguration);


}
}
  1. Now you need to customize the CORS configuration based on your need:

    • setAllowedHeaders-> you have to specify which parameters are allowed to be sent to the backend services through the front-end app, for example, if you are using Bearer/Basic Token Authorization methods, you need to pass your JWT-Token through the "Authorization" header. So you need to make sure that backed would accept this data accordingly and for this purpose, you must put "Authorization" in the list of Allowed-Headers.

    • setAllowedMethods-> Do not forget to put "OPTIONS" method in the list for Pre-flight process. Don't worry, read more here!

    • setAllowCredentials-> If you are using Authorization header, set it True.

    • setExposedHeaders-> If you are returning data through Response Headers, you need to specify them here. for example, some APIs are designed to return Authorization token after success /authentication through Response Headers. Thus, the related header needs to be exposed accordingly.

    • setAllowedOrigins-> You must specify the domains that are eligible to send requests to your backend applications. for example, if your application is hosted on https://penguin.com and your APIs are on https://api.penguin.com, you need to allow "https://penguing.com" to send requests to your backend. Also, you are able to pass wildcard (*) to allow any domains to send requests to your backend. But it's recommended to not use "any" unless you are providing public APIs or you are deploying in the non-production environments.

    There is an important misunderstanding for the people that may think CORS can avoid misuses of the APIs by/on other platforms (i.e phishing purposes). It's not true, CORS Policies are browser-based policies and can be bypassed easily through proxies, so it only makes the misuse process a little bit harder, but it does not make immunity.

  2. Build/Run your application, Test your APIs, and rest ( Everyone knows CORS headache )

Alternative Solutions

You can use the following links:

Spring.io | Enabling Cross-Origin Requests for a RESTful Web Service

Bealdung | CORS with Spring

// CorsConfig.java file
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowCredentials(true);
}
}


As of 2021, this is maybe the simplest solution, just need to create a separate class.

That's all.

Note that new CorsConfiguration().applyPermitDefaultValues() only allows GET, POST and HEAD methods. If you are looking for PUT or DELETE, you have to set the methods manually (like below). Finally, don't forget the OPTIONS method which is required to preflight PUT, PATCH and DELETE methods (CORS error will still occur otherwise).

import static org.springframework.web.cors.CorsConfiguration.ALL;


@Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowedMethods(Arrays.asList(
HttpMethod.GET.name(),
HttpMethod.POST.name(),
HttpMethod.DELETE.name(),
HttpMethod.PUT.name(),
HttpMethod.HEAD.name(),
HttpMethod.POST.name(),
HttpMethod.OPTIONS.name()
));
config.setAllowedHeaders(Collections.singletonList(ALL));
config.setAllowedOrigins(Collections.singletonList(ALL));
config.setMaxAge(1800L);
source.registerCorsConfiguration("/**", config);
return source;
}

You need to look at especially this method : configure( HttpSecurity httpSecurity )

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;


@Autowired
private UserDetailsService jwtUserDetailsService;


@Autowired
private JwtRequestFilter jwtRequestFilter;


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}


@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}


@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}


public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*")
.allowedMethods("HEAD", "GET", "PUT", "POST",
"DELETE", "PATCH").allowedHeaders("*");
}


@Override
protected void configure(HttpSecurity http) throws Exception {
        

http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/images/**").permitAll()
.antMatchers(HttpMethod.POST,"/api/login").permitAll()
.antMatchers(HttpMethod.POST,"/api/user").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Add our custom JWT security filter
UsernamePasswordAuthenticationFilter.class);
}
    

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().configurationSource(request -> {
var cors = new CorsConfiguration();
cors.setAllowedOrigins(List.of("http://localhost:4200", "http://127.0.0.1:80", "http://example.com"));
cors.setAllowedMethods(List.of("GET","POST", "PUT", "DELETE", "OPTIONS"));
cors.setAllowedHeaders(List.of("*"));
return cors;
}).and()...
}
}

In class implement WebMvcConfigurer you have to Override method addCorsMappings

public class WebMvcConfig implements WebMvcConfigurer {


private final long MAX_AGE_SECS;




@Value("${appConfig.cors.allowedOrigins}")
private String[] allowedOrigins;


public WebMvcConfig() {
MAX_AGE_SECS = 3600;
}


@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(allowedOrigins)
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(MAX_AGE_SECS);
}
}