refer: https://spring.io/blog/2015/06/08/cors-support-in-spring-framework 使用springboot时,处理全局跨域: If you are using Spring Boot, it is recommended to just declare a WebMvcConfigurer bean as following

  1. @Configuration
  2. public class MyConfiguration {
  3. @Bean
  4. public WebMvcConfigurer corsConfigurer() {
  5. return new WebMvcConfigurerAdapter() {
  6. @Override
  7. public void addCorsMappings(CorsRegistry registry) {
  8. registry.addMapping("/**");
  9. }
  10. };
  11. }
  12. }

但是有了spring security需要在设置一下,不然options请求会被spring security拦截:

If you are using Spring Security, make sure to enable CORS at Spring Security level as well to allow it to leverage the configuration defined at Spring MVC level.

spring security设置cors

refer:https://docs.spring.io/spring-security/site/docs/current/reference/html5/#cors

Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.

The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:

@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(withDefaults())
            ...
    }

    @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;
    }
}

If you are using Spring MVC’s CORS support, you can omit specifying the CorsConfigurationSource and Spring Security will leverage the CORS configuration provided to Spring MVC. 有了SpringMVC的设置,就不要配置CorsConfigurationSource 了

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
            // Spring Security will use CORS configuration provided to Spring MVC
            .cors(withDefaults())
            ...
    }
}

搭配nginx

springmvc设置允许跨域:


/**
 * 跨域配置
 */
@Configuration
public class CorsConfig{

    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").
                        allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
                        allowedMethods("*"). //允许任何方法(post、get等)
                        allowedHeaders("*"); //允许任何请求头
            }
        };
    }
}

springSecurity设置了开启CORS:



/**
 * @author LGH
 */
@Configuration
@Order(90)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
                // Spring Security will use CORS configuration provided to Spring MVC
                //会用WebMvcConfigurer的cors配置
                .cors();
    }
    //
    // @Bean
    // CorsConfigurationSource corsConfigurationSource() {
    //     CorsConfiguration configuration = new CorsConfiguration();
    //     configuration.setAllowedOrigins(Arrays.asList("*"));
    //     configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS","PUT","DELETE"));
    //     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    //     source.registerCorsConfiguration("/**", configuration);
    //     return source;
    // }


}

这样还是不行,因为没有处理OPTIONS请求,需要在NGINX处理OPTIONS请求:


location /api/app/ {

    #允许跨域
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
            add_header 'Access-Control-Allow-Headers' '*' always;
            add_header 'Access-Control-Max-Age' 1728000 always;
            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            return 204;
        }

    #if ($request_method ~* '(GET|POST|DELETE|PUT)') {
        #add_header 'Access-Control-Allow-Origin' '*' always;

        #add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type' always;
    #}
    rewrite ^/api/app/(.*)$ /$1 break;
    proxy_pass http://127.0.0.1:9310;
}

这样就好了。Java中应该也可以配置OPTIONS请求,如用filter,但是得放在SpringSecurity的权限检验前,因为OPTIONS请求没有Authorization请求头,会被直接判断无权限。