只要与当前浏览器访问的url不同(协议,域名,端口号),就会产生跨域。
1. 配置文件解决,在gateway的配置文件中
- spring:
- cloud:
- gateway:
- globalcors:
- cors-configurations:
- '[/**]':
- allowedOrigins: "*"
- allowedHeaders: "*"
- allowedMethods: "*"
- default-filters:
- - DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
注:要加上最下边的配置,不然浏览器还是会报跨域问题,因为浏览器Vary
和 Access-Control-Allow-Origin
两个头重复了两次,其中浏览器对后者有唯一性限制!
2.配置类
- @Component
- public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {
-
- private static final Logger logger = LoggerFactory.getLogger(CorsResponseHeaderFilter.class);
-
- private static final String ANY = "*";
-
- @Override
- public int getOrder() {
- // 指定此过滤器位于NettyWriteResponseFilter之后
- // 即待处理完响应体后接着处理响应头
- return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
- }
-
- @Override
- @SuppressWarnings("serial")
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- return chain.filter(exchange).then(Mono.fromRunnable(() -> {
- exchange.getResponse().getHeaders().entrySet().stream()
- .filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
- .filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
- || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
- || kv.getKey().equals(HttpHeaders.VARY)))
- .forEach(kv ->
- {
- // Vary只需要去重即可
- if(kv.getKey().equals(HttpHeaders.VARY))
- kv.setValue(kv.getValue().stream().distinct().collect(Collectors.toList()));
- else{
- List
value = new ArrayList<>(); - if(kv.getValue().contains(ANY)){ //如果包含*,则取*
- value.add(ANY);
- kv.setValue(value);
- }else{
- value.add(kv.getValue().get(0)); // 否则默认取第一个
- kv.setValue(value);
- }
- }
- });
- }));
- }
- }