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

Spring Boot 3.1+Spring Security与Angular 16的CORS问题求助

解决Spring Boot 3.1 + Spring Security跨域/login接口CORS错误的方案

1. 确保Spring Security的CORS配置覆盖/login端点且顺序正确

Spring Security过滤器链的执行顺序直接影响CORS规则生效范围,cors()配置必须优先于权限校验、CSRF等配置,否则/login请求可能绕过CORS处理逻辑。

修改你的SecurityConfig配置类:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 先启用CORS配置
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(csrf -> csrf.disable()) // 若无需CSRF可暂时关闭测试,后续按需开启
            .authorizeHttpRequests(auth -> auth
                // 放行/login的OPTIONS预检请求和POST登录请求
                .requestMatchers(HttpMethod.OPTIONS, "/login").permitAll()
                .requestMatchers("/login").permitAll()
                .anyRequest().authenticated()
            );
        return http.build();
    }

    // 定义全局CORS配置源
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 指定允许的客户端Origin
        configuration.setAllowedOrigins(List.of("http://client.example.com"));
        // 允许的HTTP方法,包含预检OPTIONS和登录用的POST
        configuration.setAllowedMethods(List.of("GET", "POST", "OPTIONS"));
        // 允许的请求头,根据登录请求实际需求调整
        configuration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
        // 允许携带凭证(如Cookie)
        configuration.setAllowCredentials(true);
        // 暴露给前端的响应头(若需要返回Token等)
        configuration.setExposedHeaders(List.of("Authorization"));
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 将配置应用到所有端点,确保/login被覆盖
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

2. 自定义/login接口的响应头兜底处理

如果你的/login是自定义Controller接口,通过WebClient调用Keycloak后返回响应,若Spring的CORS过滤器未生效,可在接口方法中手动添加CORS头作为兜底:

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    // 调用Keycloak获取Token的逻辑
    Mono<KeycloakTokenResponse> tokenResponse = webClient.post()
            .uri("http://keycloak.example.com/realms/your-realm/protocol/openid-connect/token")
            .bodyValue(buildLoginFormData(request))
            .retrieve()
            .bodyToMono(KeycloakTokenResponse.class);
    
    return tokenResponse.map(response -> ResponseEntity.ok()
            .header("Access-Control-Allow-Origin", "http://client.example.com")
            .header("Access-Control-Allow-Credentials", "true")
            .body(response)
    ).block();
}

3. 移除WebFlux CORS配置避免冲突

若之前添加了WebFlux独立的CORS配置,会和Spring Security的CORS配置产生冲突(Security过滤器优先级更高),需删除重复配置,仅保留Security层面的CORS规则。

4. 验证预检请求响应

用curl测试OPTIONS预检请求,确认响应包含正确的CORS头:

curl -X OPTIONS http://api.example.com/login \
  -H "Origin: http://client.example.com" \
  -H "Access-Control-Request-Method: POST"

正常响应应包含以下头信息:

Access-Control-Allow-Origin: http://client.example.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Credentials: true

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:26:08