You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用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:
@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()

验证步骤

  1. 清理冲突配置,保留一种CORS规则;
  2. 根据是否需携带Cookie调整允许源设置;
  3. 确保请求路径被Spring Security放行;
  4. 优先用同协议页面测试(如本地HTTP页面请求HTTP服务器),排除混合内容干扰;
  5. 查看控制台报错,区分是CORS错误还是混合内容错误。

内容的提问来源于stack exchange,提问作者Sophia Okito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 21:31:17