SpringCloud-Gateway 解决跨域问题
什么是跨域 ?
广义: 指一个域下的文档或脚本试图去请求另一个域下的资源。
狭义: 浏览器不能执行其他网站的脚本,是由浏览器同源策略限制的一类请求场景,从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。
1.基于配置文件的跨域配置
你可以在 application.yml 或 application.properties 配置文件中设置 CORS 规则。例如:
spring:
cloud:
gateway:
# 全局的跨域配置
globalcors:
# 解决 options请求被拦截问题
add-to-simple-url-handler-mapping: true
cors-configurations:
# 拦截的请求
'[/**]':
# 允许跨域的请求
allowedOrigins: "*" # spring boot2.4以前的配置
# allowedOriginPatterns: "*" # spring boot2.4以后的配置
# 允许请求中携带的头信息
allowedHeaders: "*"
# 运行跨域的请求方式
allowedMethods: "*"
# 是否允许携带cookie
alloweCredentials: true
# 跨域检测的有效期,单位s
maxAge: 360002.基于 Java 配置的跨域配置
除了在配置文件中设置,你也可以在 Java 类中配置 Spring Cloud Gateway 的跨域支持。这可以通过 CorsWebFilter 来完成。
创建 CorsWebFilter Bean:
//加配置文件
@Configuration
public class CorsConfig {
//跨域检测的有效期,单位s
private static final String MAX_AGE = "18000L";
//支持跨域的域名,可放在配置文件里面
@Value("${cors.whitelist}")
private List<string> CORS WHITELIST;
@Bean
public WebFilter corsFilter() {
return (ServerWebExchangectx,WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request)) {
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers = response.getHeaders();
string origin = requestHeaders.getorigin();
if (CORS_WHITELIST.contains(origin) Il CollectionUtils.isEmpty(CORS WHITELIST)) {
headers.add(HttpHeaders.ACCESS_CONTROL ALLOW ORIGIN,origin);}
else {
headers.add(HttpHeaders.ACCESS_CONTROL ALLOW ORIGIN, CORS_WHITELIST.get(0));
}
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,requestHeaders.getAccessControlRequestHeaders());
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS,headerValue:"true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS,headerValue:"*");
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE,MAX AGE);
if (request.getMethod() == HttpMethod.OPTIONS){
response.setstatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter (ctx);
};
}3.基于 Route 配置跨域(限特定路由)
你还可以基于路由配置 CORS 规则,这样只对特定的路由应用跨域设置。你可以在 Spring Cloud Gateway 的路由配置中使用 cors() 方法来实现。
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/api/**")
.filters(f -> f.cors(cors -> cors.allowedOrigins("*"))
.addRequestHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
.addRequestHeader("Access-Control-Allow-Headers", "Authorization, Content-Type"))
.uri("http://localhost:8081"))
.build();
}
}在这个例子中:
- 通过 cors() 方法为 /api/** 路由路径配置了跨域规则。
- 使用 addRequestHeader 添加了 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers 请求头,以支持跨域请求。
4.解决预检请求(OPTIONS)
跨域请求有时会触发预检请求(OPTIONS 请求),它是浏览器自动发起的一种请求,检查实际请求是否安全可接受。如果你的网关处理预检请求不当,可能会出现跨域问题。
你可以通过添加 OPTIONS 请求的处理来解决这个问题。确保你的网关可以处理预检请求:
spring:
cloud:
gateway:
routes:
- id: api_route
uri: http://localhost:8081
predicates:
- Path=/api/**
filters:
- name: AddRequestHeader
args:
name: Access-Control-Allow-Origin
value: "*"
- name: AddRequestHeader
args:
name: Access-Control-Allow-Methods
value: "GET, POST, PUT, DELETE, OPTIONS"
- name: AddRequestHeader
args:
name: Access-Control-Allow-Headers
value: "Authorization, Content-Type"
- name: AddRequestHeader
args:
name: Access-Control-Allow-Credentials
value: "true"或者,你也可以通过在 Spring Cloud Gateway 中直接添加预检请求的过滤器来自动处理 OPTIONS 请求。
5.配置 CORS 和 Spring Security 兼容
如果你的 Spring Cloud Gateway 后端服务启用了 Spring Security,也可能会遇到跨域请求的问题,尤其是在涉及认证(如 JWT)时。为了确保 CORS 配置与 Spring Security 配置不冲突,你需要在 Spring Security 配置中显式启用 CORS 支持。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and() // 启用 CORS
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated();
}
}在这里,http.cors().and() 启用了 CORS 支持,并允许跨域请求。
















