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

Spring Boot配置Spring Security CORS仍报错,求排查方案

排查Spring Boot + React CORS问题:Postman正常但前端报错的解决思路

嘿,我之前踩过一模一样的坑!Postman能正常请求但React一调用就报CORS错,核心原因其实是浏览器的预检请求(OPTIONS)没被正确处理——Postman不会自动发OPTIONS预检,但React在发送带自定义头(比如你的JWT Token)或者非简单请求时,浏览器会先发起OPTIONS请求确认权限,这时候你的Security配置可能把这个预检请求拦截了。

咱们一步步来修正:

1. 先给OPTIONS请求开绿灯

你的Security配置里只放行了POST /login,但OPTIONS请求是浏览器自动发起的,还没带JWT Token,肯定会被拦截。在authorizeRequests里加一行,放行所有OPTIONS请求:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors().and().csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .addFilter(new JwtAuthenticationFilter(authenticationManager()))
        .addFilter(new JwtAuthorizationFilter(authenticationManager(), this.userRepository))
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 新增这行,放行所有OPTIONS请求
        .antMatchers(HttpMethod.POST, "/login").permitAll()
        .antMatchers("/iotd").hasRole("USER")
        .anyRequest().authenticated();
}

2. 把CORS配置整合到Spring Security中,避免优先级冲突

你之前分开用WebMvcConfigurer配CORS,可能会被Spring Security的CORS配置覆盖。直接在Security里指定CORS配置更可靠:

第一步:移除原来的CorsConfig类(或者注释掉)

第二步:在Security配置里添加CORS配置源

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    // 注入你的userRepository...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // 替换原来的cors().and(),用自定义的配置源
            .cors(cors -> cors.configurationSource(corsConfigurationSource())).and().csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager()))
            .addFilter(new JwtAuthorizationFilter(authenticationManager(), this.userRepository))
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers(HttpMethod.POST, "/login").permitAll()
            .antMatchers("/iotd").hasRole("USER")
            .anyRequest().authenticated();
    }

    // 新增CORS配置源Bean
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("*")); // 生产环境一定要改成你的前端域名,比如"http://localhost:3000"
        config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setAllowCredentials(true); // 如果前端要带Cookie/认证信息,必须设为true,同时origin不能是*

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

3. 确保JWT过滤器跳过OPTIONS请求

你的JwtAuthenticationFilter和JwtAuthorizationFilter可能会拦截OPTIONS请求,导致预检失败。在过滤器的doFilterInternal方法开头加判断,直接放行OPTIONS请求:

以JwtAuthenticationFilter为例:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    // 新增:如果是OPTIONS请求,直接返回200
    if (HttpMethod.OPTIONS.name().equals(request.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    }
    // 原来的JWT验证逻辑...
    chain.doFilter(request, response);
}

JwtAuthorizationFilter也要做同样的修改!

最后验证

重启Spring Boot应用,再用React调用试试——应该就能正常跨域了。另外提醒下,生产环境千万不要用allowedOrigins("*"),要指定具体的前端域名,避免安全风险。

内容的提问来源于stack exchange,提问作者Bjorn Kristensson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:59:29