Spring Boot 2.6.6 @CrossOrigin注解CORS跨域配置不生效问题
Spring Boot 2.6 + Spring Security 跨域配置失效修复
问题根因
@CrossOrigin注解、WebMvcConfigurer重写addCorsMappings、自定义普通CORS过滤器全部失效的核心原因:Spring Security过滤器链执行优先级高于Spring MVC层的所有拦截处理逻辑,跨域请求到达服务端后,会先被Security过滤器拦截,根本不会走到MVC层配置的CORS规则处理流程,最终返回的响应里完全没有Access-Control-Allow-*系列CORS响应头,直接触发浏览器跨域拦截。
另外当前接口是multipart/form-data类型的POST请求,属于跨域非简单请求,浏览器会先发送OPTIONS方法的预检请求,现有配置下这个预检请求会被全局认证规则拦截,也是导致跨域报错的直接诱因。
修复步骤(推荐方案,改动最小)
- 在Spring Security配置中开启CORS支持
不需要删除之前写好的MVC层CORS配置,只需要在Security的HttpSecurity配置开头加上.cors()配置,Security会自动拾取所有已定义的CORS规则(包括WebMvcConfigurer里的全局规则、控制器上@CrossOrigin的单接口规则),在过滤器链靠前的位置完成跨域响应头注入。 - 放行所有OPTIONS预检请求
跨域预检的OPTIONS请求不会携带JWT等认证凭证,必须配置放行,否则会直接返回403状态码。
修改后的Security配置核心代码如下:
@Override public void configure(HttpSecurity http) throws Exception { http.cors().and() // 新增行:开启Security层CORS处理 .csrf().disable() .authorizeRequests() .antMatchers("/authenticate").permitAll() // 新增行:放行所有跨域预检OPTIONS请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated() .and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); }
备选方案(自定义高优先级CORS过滤器)
如果需要完全自定义CORS规则,不依赖MVC层配置,可以直接在配置类中声明CorsFilter类型的Bean,Spring Security会自动将其注册到过滤器链的高优先级位置,不需要手动调整过滤器顺序:
@Bean public CorsFilter corsFilter() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowedOrigins(List.of("http://localhost:3000")); corsConfig.setAllowedMethods(List.of("GET", "POST", "OPTIONS")); corsConfig.setAllowedHeaders(List.of("*")); corsConfig.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig); return new CorsFilter(source); }
注意:该方案依然需要在Security配置中加上.cors()和OPTIONS请求放行的配置。
验证方式
配置修改完成重启服务后,再发起接口调用,查看响应头如果包含Access-Control-Allow-Origin: http://localhost:3000字段,就说明CORS规则已经生效,前端不会再报跨域错误。
内容的提问来源于stack exchange,提问作者Toji
相关产品推荐
相关产品推荐

