Spring Cloud Gateway CORS配置失效,跨域请求遭拦截求助
CORS拦截问题:Spring Cloud Gateway + OAuth2资源服务器下预检请求无
Access-Control-Allow-Origin头 错误信息
从源'null'访问'http://localhost:8765/conversion/convert'的XMLHttpRequest已被CORS策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在'Access-Control-Allow-Origin'标头。
前端请求代码(jQuery)
$.ajax({ type: 'POST', url: 'http://localhost:8765/conversion/convert', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer MY_JWT_TOKEN' }, data: JSON.stringify({ id: 1, from: 'usd', to: 'bdt', quantity: 100 }), success: function(data) { console.log(data); }, error: function(error) { console.error(error); } });
后端依赖版本
- spring-cloud-gateway: 2022.0.4
- spring-cloud-starter-gateway: 3.1.6
- spring-boot-starter-oauth2-resource-server: 3.1.6
- spring-cloud-starter-netflix-eureka-client
当前网关配置(application.yml)
spring: security: oauth2: resourceserver: jwt: issuer-ui: http://localhost:9000/realms/Microservices-demo-realm jws-algorithm: RS256 cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: "*" allowedMethods: "*" allowedHeaders: "*" default-filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin RETAIN_UNIQUE - name: TokenRelay routes: - id: conversion-service uri: lb://currency-conversion predicates: - Path=/conversion/**
问题现象截图
- Chrome网络控制台:

- React应用CORS拦截:

解决方案
1. 放行OPTIONS预检请求(核心修复)
启用OAuth2资源服务器后,Spring Security会优先拦截请求,OPTIONS预检请求会被安全规则拦截,导致Gateway的CORS逻辑无法执行。需要显式放行OPTIONS请求:
创建Spring Security配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; @Configuration @EnableWebFluxSecurity public class SecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { http .csrf(ServerHttpSecurity.CsrfSpec::disable) .authorizeExchange(exchanges -> exchanges // 无条件放行OPTIONS预检请求 .pathMatchers(org.springframework.http.HttpMethod.OPTIONS).permitAll() // 其他请求需认证 .anyExchange().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> {})); return http.build(); } }
2. 优化Gateway CORS配置
调整全局CORS配置,补充必要参数并明确规则:
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: "*" # 若前端需带凭证,替换为具体域名如"http://localhost:3000" allowedMethods: GET, POST, PUT, DELETE, OPTIONS allowedHeaders: "*" allowCredentials: true # 前端带cookie/凭证时开启 maxAge: 3600 # 预检请求缓存时长,减少重复请求 default-filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin RETAIN_UNIQUE - name: TokenRelay
3. 排查TokenRelay过滤器影响
TokenRelay用于传递OAuth2令牌,但OPTIONS请求不会携带Authorization头,可调整路由过滤器仅在非OPTIONS请求生效:
routes: - id: conversion-service uri: lb://currency-conversion predicates: - Path=/conversion/** filters: - name: TokenRelay args: enabled: true - RemoveRequestHeader=Cookie # 可选,避免传递不必要的Cookie
4. 处理源为'null'的场景
直接打开本地HTML文件(file://协议)会导致源为'null',部分浏览器对allowedOrigins: "*"支持有限。建议将前端部署到HTTP服务器(如http://localhost:8080),并在CORS配置中指定该源:
allowedOrigins: "http://localhost:8080"
5. 验证请求流转
添加日志过滤器确认OPTIONS请求是否到达Gateway:
spring: cloud: gateway: default-filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin RETAIN_UNIQUE - name: TokenRelay - name: RequestLogging args: includeHeaders: true includeQueryString: true includePayload: true
查看日志确认OPTIONS请求是否被正确处理,以及响应头是否包含Access-Control-Allow-Origin。
内容的提问来源于stack exchange,提问作者Naim
相关产品推荐
相关产品推荐

