Angular请求Spring Gateway触发CORS错误,涉及OAuth2与Keycloak
问题分析与解决办法
问题根源
你遇到的CORS错误本质是OPTIONS预检请求被触发了重定向,而浏览器禁止预检请求的响应是重定向。结合你观察到的Origin字段为null,问题出在两个核心环节:
- Spring Gateway转发OPTIONS请求时,要么丢失了Angular发送的
Origin头,要么让OPTIONS请求进入了OAuth2认证流程,触发了到Keycloak的重定向; - Keycloak的CORS配置未正确覆盖你的客户端域名,导致重定向响应的CORS头不合法。
分步解决
1. 让OPTIONS请求跳过OAuth2认证
预检请求是浏览器自动发送的,不需要携带认证信息,必须直接放行,避免触发到Keycloak的重定向。修改Gateway的Security配置:
@Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http .authorizeExchange(exchanges -> exchanges .pathMatchers(HttpMethod.OPTIONS).permitAll() // 放行所有OPTIONS请求 .anyExchange().authenticated() ) .oauth2Login(withDefaults()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(withDefaults())); return http.build(); }
2. 修正Gateway的CORS全局配置
确保Gateway正确转发Origin头,并且避免重复添加CORS响应头:
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowed-origins: "http://localhost:4200" # 替换成你的Angular实际域名 allowed-methods: "*" allowed-headers: "*" allow-credentials: true default-filters: - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE
3. 配置Keycloak的客户端CORS
登录Keycloak控制台,找到你的Angular客户端:
- 进入
Settings标签页,在Web Origins中添加你的Angular域名(比如http://localhost:4200),生产环境建议精确配置,不要用*; - 确认
Access Type设置为public(Angular作为前端单页应用,适合用public类型)。
4. 排查Origin为null的原因
添加一个简单的过滤器,打印Gateway接收到的请求头,确认Origin是否被正确传递:
@Component public class OriginLoggingFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { String origin = exchange.getRequest().getHeaders().getOrigin(); System.out.println("Received Origin: " + origin); return chain.filter(exchange); } }
- 如果打印结果是
null,检查Angular的请求配置:确保请求是跨域发送的,Angular的HttpClient默认会发送Origin头,除非请求是同域(但同域不会触发CORS); - 如果打印有正确的Origin,说明之前的CORS配置未生效,检查Gateway的配置优先级(比如自定义的
CorsWebFilter是否覆盖了全局配置)。
验证
重启Gateway和Angular应用,发送GET请求后查看浏览器Network面板:
- OPTIONS请求的响应状态码应为200,且响应头包含正确的
Access-Control-Allow-Origin; - 后续的GET请求不会再触发CORS错误。
内容的提问来源于stack exchange,提问作者alexmntmnk
相关产品推荐
相关产品推荐

