SpringCloud Gateway解决CROS跨域问题

目录

一、问题

二、原因

二、解决方法

1、gateway设置允许跨域

[2、手动写一个 CorsResponseHeaderFilter 的 GlobalFilter 去修改Response中的头](#2、手动写一个 CorsResponseHeaderFilter 的 GlobalFilter 去修改Response中的头)


一、问题

前端代码访问后端代码时候会出现

复制代码
Access to XMLHttpRequest at 'http://localhost:8080/user/logout' from origin 'http://localhost:8800' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

这种报错,前端会显示不允许有多个'Access-Control-Allow-Origin' CORS头

二、原因

仔细查看返回的响应头,里面包含了两份Access-Control-Allow-Origin头。

二、解决方法

1、gateway设置允许跨域

使用yml格式去设置允许跨域

java 复制代码
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
      default-filters:
        - DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST

2、手动写一个 CorsResponseHeaderFilterGlobalFilter 去修改Response中的头

java 复制代码
@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<String> value = new ArrayList<>();
                            if(kv.getValue().contains(ANY)){  //如果包含*,则取*
                                value.add(ANY);
                                kv.setValue(value);
                            }else{
                                value.add(kv.getValue().get(0)); // 否则默认取第一个
                                kv.setValue(value);
                            }
                        }
                    });
        }));
    }
}

引用:地址

相关推荐
码云数智-园园2 天前
C++20 Modules 模块详解
java·开发语言·spring
咖啡八杯2 天前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
Flittly2 天前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring
李少兄2 天前
从原理到实战:Spring IoC/DI 核心知识体系与高频面试题全解
java·后端·spring
shushangyun_2 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
慧一居士2 天前
Feign的GET请求如何传递对象参数?
java·spring cloud
ofoxcoding2 天前
在AI API聚合平台配置DeepSeek V3.2提示词缓存实战:快速接入与成本优化指南
人工智能·spring·缓存·ai
一杯奶茶¥2 天前
水果销售网站 CRM客户信息管理系统 超市管理系 酒店管理系统 健身房管理系统 在线音乐网站 校园招聘系统
java·vue.js·spring boot·mysql·spring·java项目
摇滚侠2 天前
SpringMVC 入门到实战 RESTFul 49-55
java·开发语言·后端·spring·intellij-idea·restful
我登哥MVP2 天前
SpringCloud Alibaba 核心组件解析:服务链路追踪
java·spring boot·后端·spring·spring cloud·java-ee·maven