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

配置CORS映射后Spring Security WebFlux仍存在跨域问题

问题分析与解决

你的配置存在以下几个问题,导致CORS策略失效:

1. CORS配置中allowedOrigins格式错误

浏览器的Origin包含协议前缀(如http://localhost:4200),你当前配置的localhost:4200缺少协议,导致CORS规则无法匹配请求的Origin,服务器不会返回Access-Control-Allow-Origin响应头。

2. 重复定义ReactiveAuthenticationManager Bean

你同时定义了两个ReactiveAuthenticationManager类型的Bean,Spring容器无法确定使用哪一个,会导致认证流程异常,进而影响请求处理(包括CORS响应头的生成)。

3. allowedHeaders包含无效的响应头字段

Access-Control-Allow-Origin是服务器返回的响应头,不是客户端请求的头字段,不需要添加到allowedHeaders中,该配置项仅用于指定允许的请求头。

4. Preflight(OPTIONS)请求被认证拦截

浏览器发送的CORS预请求(OPTIONS)不会携带认证信息,但你的安全配置中设置了anyExchange().authenticated(),导致OPTIONS请求被拦截,无法正常返回CORS响应头。


修正后的配置代码

1. 修正CORS配置(WebConfig.java)

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                // 补充协议前缀
                .allowedOrigins("http://localhost:4200")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                // 移除无效的响应头,保留实际需要的请求头
                .allowedHeaders("Authorization", "Content-Type")
                // 允许携带认证信息(HTTP Basic认证需要)
                .allowCredentials(true);
    }
}

2. 修正安全配置(SecurityConfig.java)

移除重复的ReactiveAuthenticationManager Bean,同时允许OPTIONS请求无需认证:

@Configuration
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http){
        return http
                .cors().and()
                .csrf().disable()
                .authorizeExchange()
                // 允许OPTIONS请求无需认证,处理CORS预请求
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                // 其他请求需要认证
                .anyExchange().authenticated()
                .and()
                .httpBasic()
                .and()
                .build();
    }

    // 保留一个正确的ReactiveAuthenticationManager Bean
    @Bean
    public ReactiveAuthenticationManager authenticationManager(ReactiveUserDetailsService userDetailsService,
                                                               PasswordEncoder passwordEncoder){
        UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
        manager.setPasswordEncoder(passwordEncoder);
        return manager;
    }

    @Bean
    public PasswordEncoder noPasswordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
}

额外说明

  • allowCredentials(true)必须设置,因为HTTP Basic认证需要携带用户凭证,浏览器要求服务器明确允许该属性才能发送认证信息。
  • 确保你的Angular请求中设置了withCredentials: true(使用HttpClient时),例如:
this.http.get('http://localhost:8080/course/my-courses', { withCredentials: true });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:30:26