启用CORS后SpringBoot应用仍持续出现CORS错误的排查求助
SpringBoot 跨域(CORS)错误排查与解决方案
问题场景
搭建的SpringBoot服务器持续出现CORS错误,尝试过多种配置调整,甚至将Java版本从17降级到11,问题仍未解决。在Safari控制台测试时,收到以下报错:
- [blocked] 页面
https://www.google.com/?client=safari&channel=mac_bm不允许显示来自http://localhost:3000/api/v1/userapi/auth/app-status的不安全内容;- “Not allowed to request resource”(不允许请求资源);
- “Fetch API cannot load http://localhost:3000/api/v1/userapi/auth/app-status due to access control checks”(由于访问控制检查,Fetch API无法加载该资源)。
以下为当前使用的Web安全配置及自定义CORS过滤器代码:
Web安全配置代码
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @RequiredArgsConstructor public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final TokenProvider tokenProvider; private final CustomAuthenticationProvider customAuthenticationProvider; private final UserModelDetailsService userModelDetailsService; private final MyCORSFilter corsFilter; private final JwtAuthenticationEntryPoint authenticationErrorHandler; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(new DBAuthenticationProvider(userModelDetailsService)); auth.authenticationProvider(customAuthenticationProvider); } @Override public void configure(WebSecurity web) { web.ignoring() .antMatchers(HttpMethod.OPTIONS, "/**") .antMatchers("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", "/h2-console/**"); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable().cors().configurationSource(corsConfigurationSource()).and() .addFilterBefore(corsFilter, ChannelProcessingFilter.class) .exceptionHandling() .authenticationEntryPoint(authenticationErrorHandler) .accessDeniedHandler(jwtAccessDeniedHandler) .and() .headers() .frameOptions() .sameOrigin() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/auth/**").permitAll() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", "/h2-console/**").permitAll() .antMatchers("/documentation/**", "/swagger-resources/**", "/v3/**", "/swagger-ui.html", "/swagger-ui/**").permitAll() .anyRequest().authenticated() .and() .apply(securityConfigurerAdapter()); } private JWTConfigurer securityConfigurerAdapter() { return new JWTConfigurer(tokenProvider); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.addAllowedOrigin("*"); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
自定义CORS过滤器代码
@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class MyCORSFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; System.out.println("i am here 000"); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH, PUT, HEAD"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "*"); if ("OPTIONS".equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void init(FilterConfig filterConfig) { } @Override public void destroy() { } }
问题根源与解决建议
1. 配置冲突
当前同时启用了Spring Security内置CORS配置和自定义过滤器,两者规则可能冲突,需二选一:
方案一:保留内置配置,移除自定义过滤器
- 删除
MyCORSFilter类,或去掉@Component注解使其失效; - 调整内置CORS配置:
- 若需携带Cookie,
addAllowedOrigin("*")与Allow-Credentials: true不能共存,需指定具体域名,或改用Spring Boot 2.4+推荐的AllowedOriginPatterns:
- 若需携带Cookie,
@Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 允许所有源的模式写法,支持带凭证 configuration.setAllowedOriginPatterns(Collections.singletonList("*")); configuration.setAllowedHeaders(Collections.singletonList("*")); configuration.setAllowedMethods(Collections.singletonList("*")); configuration.setAllowCredentials(true); // 不需要携带Cookie可删除此行 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
方案二:保留自定义过滤器,移除内置配置
- 在
HttpSecurity配置中删除.cors().configurationSource(corsConfigurationSource()).and()行; - 调整过滤器响应头:若需携带Cookie,
Access-Control-Allow-Origin不能设为*,需指定具体域名,如:
response.setHeader("Access-Control-Allow-Origin", "https://www.google.com"); response.setHeader("Access-Control-Allow-Credentials", "true");
2. Safari混合内容限制
当前场景是HTTPS页面请求HTTP资源,Safari默认阻止此类混合内容,这并非单纯CORS问题:
- 临时解决:开启Safari开发菜单(偏好设置->高级->勾选“显示开发菜单”),选择“禁用本地文件限制”,或关闭隐私设置中的“阻止跨站点跟踪”;
- 长期解决:为本地服务器配置HTTPS(可使用自签名证书测试)。
3. 请求路径未放行
当前配置仅放行/auth/**路径,但请求路径为/api/v1/userapi/auth/app-status,需添加对应放行规则:
.antMatchers("/api/v1/userapi/auth/**").permitAll()
验证步骤
- 清理冲突配置,保留一种CORS规则;
- 根据是否需携带Cookie调整允许源设置;
- 确保请求路径被Spring Security放行;
- 优先用同协议页面测试(如本地HTTP页面请求HTTP服务器),排除混合内容干扰;
- 查看控制台报错,区分是CORS错误还是混合内容错误。
内容的提问来源于stack exchange,提问作者Sophia Okito
相关产品推荐
相关产品推荐

