Spring Boot:CORS 问题

Posted

技术标签:

【中文标题】Spring Boot:CORS 问题【英文标题】:Spring Boot : CORS Issue 【发布时间】:2019-01-14 03:17:22 【问题描述】:

我正在使用 Spring Boot 版本 2.0.2Release。 以下是我的安全配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
@ComponentScan("com.mk")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    private AuthenticationProvider myAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable();
        http.cors().configurationSource(corsConfigurationSource())
                .and()
                .csrf().disable()
                .anonymous().and()
                .authorizeRequests()
                .antMatchers(HttpMethod.GET,"/index.html").permitAll()
                .antMatchers(HttpMethod.POST,"/login").permitAll()
                .antMatchers(HttpMethod.GET,"*").authenticated()
                .and().httpBasic();
    
    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

由于 CORS 问题,我无法调用任何 API(包括登录 permitAll)。

在我得到的浏览器上(它适用于 Postman,因为那里没有进行 CORS 检查)

无法加载http://localhost:8080/myurl:对预检的响应 请求未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 使用权。响应的 HTTP 状态代码为 403。

【问题讨论】:

【参考方案1】:

虽然 Spring security 提供了一种在 http 配置器中配置 CORS 的方法,但是有一种更简洁的方法可以将 CORS 过滤器添加到应用程序中——

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


@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);


@Override
public void init(FilterConfig filterConfig) 


@Override
public void destroy() 



以最高优先级排序过滤器可确保 javax.servlet.Filter 的 MyCORSFilter 实现是链中的第一个。希望这会有所帮助

【讨论】:

这个对我有用。唯一的问题是它在同一个请求中被多次调用。 除了您的 api 调用之外,浏览器发出的每个请求都会调用它。例如。 CSS、图标、图像等 不是 css/icons 等,因为它们托管在不同的服务器上,但让我检查一下 @MohitKanwar 尝试使用 OncePerRequestFilter ,公共类 CustomFIlter 扩展了 OncePerRequestFilter 这对我不起作用,但确实如此:***.com/a/36821971/8092044【参考方案2】:

从 Spring 中查看本指南:

https://spring.io/guides/gs/rest-service-cors/

在 Spring Boot 中添加 CORS 支持的方法很少。

使用全局配置:

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurerAdapter() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
        
    ;

并使用@CrossOrigin注解:

@CrossOrigin(origins = "http://localhost:9000")
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) 
    System.out.println("==== in greeting ====");
    return new Greeting(counter.incrementAndGet(), String.format(template, name));

【讨论】:

【参考方案3】:

无需添加任何额外的FiltersWebMvcConfigurer。主要问题是 'Access-Control-Allow-Origin' 没有出现在标头中,因为 corsConfigurationSource 没有添加必要的配置来获取相关的 CORS 响应标头。因此,我们在配置CorsConfigurationSource 时必须添加以下缺少的配置

configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");

我们必须如下配置cors CorsConfigurationSource

 @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
            .cors().configurationSource(corsConfigurationSource())
                .and()
                 .....
  

 @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        configuration.setAllowCredentials(true);
        //the below three lines will add the relevant CORS response headers
        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

如果有以下组合时遇到CORS Spring Boot 2.4.0 plus 版本的问题,请参考answer

CorsConfigurationSource#setAllowedOrigins 值为 *

CorsConfigurationSource#setAllowCredentials 值为true

【讨论】:

你为什么在setAllowedOrigins(Arrays.asList("*"))之后addAllowedOrigin("*") 是的,您可以删除以下addAllowedOrigin("*"),因为我们已经添加了setAllowedOrigins(Arrays.asList("*")),我添加只是为了说明可以添加多个选项来添加来源 但是如果您删除这些重复的行,那么它与 OP 的问题中的代码相同,不是吗?我不明白,我有你说的我的配置,但预检仍然有“No Allow Origin Header”...【参考方案4】:

好的,所以我意识到它已被弃用。如果您查看 baeldung,它会以新的方式进行操作,因为他们更新了 webmvcconfigurer:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**").allowedMethods("*").allowedOrigins(frontDomain);
    

【讨论】:

你不必使用@EnableWebMvc 我不认为。如果你有,spring boot 不会自动配置 mvc。 另外,如果您要允许所有来源,这就是您的代码所说的,那么 cors 的意义何在。 关于允许所有来源是正确的,这是我用于测试的示例代码。 好的,我猜想是这样的。

以上是关于Spring Boot:CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 和 CORS

Spring Boot 和 CORS

Spring Boot 和 CORS

如何在 Spring Boot 中使用 Spring Security 配置 CORS? [复制]

Spring boot、jwt、jersey、spring security和CORS问题

Spring Boot:CORS 问题