专栏首页JAVA后端开发spring cloud gateway跨域冲突功能的开发

spring cloud gateway跨域冲突功能的开发

gateway可以实现支持跨域功能,但如果下游也支持跨域,会出现跨域冲突。 如何解决该问题,gateway对外输出相关跨域的httpheader,只要对重复的header去掉即可。

/**
 * @author starmark
 * @date 2020/5/11  下午9:29
 */
@Slf4j
public class GatewayCorsWebFilter implements WebFilter {
    @Autowired
    private IRouteService routeService;
    private final CorsProcessor processor;

    private static List<String> configHeaderNames = new ArrayList<>();
    static{
        configHeaderNames.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS);
        configHeaderNames.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS);
        configHeaderNames.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS);
        configHeaderNames.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
        configHeaderNames.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS);

    }

    public GatewayCorsWebFilter() {
        this.processor = new DefaultCorsProcessor();
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getPath().value();
        if (url.contains("webjars") || url.contains("swagger-resources") || url.contains("/v2/api-docs") || url.contains("doc.html") || url.contains("swagger-ui.html") ||
                url.contains(".css") || url.contains(".ico") || url.contains(".js") || url.contains(".png") || url.contains(".jpg")) {
            //如果发现是css或者js文件,直接放行
            return chain.filter(exchange);
        }
        String projectCode = RequestHelper.getRequestProjectCode(request);
        Assert.hasText(projectCode, "工程编码不存在");
        CorsConfiguration corsConfiguration = routeService.getGatewayProjectCorsConfiguration(projectCode);
        boolean isValid = this.processor.process(corsConfiguration, exchange);

        if (!isValid || CorsUtils.isPreFlightRequest(request)) {
            return Mono.empty();
        }
        //解决跨域冲突的问题
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders=    HttpHeaders.writableHttpHeaders(getDelegate().getHeaders());
                dedupe(httpHeaders);
                return httpHeaders;
            }
            void dedupe(HttpHeaders headers) {
                if (headers == null) {
                    return;
                }
                for (String name : configHeaderNames) {
                    dedupe(headers, name.trim());
                }
            }

            private void dedupe(HttpHeaders headers, String name) {
                List<String> values = headers.get(name);
                if (values == null || values.size() <= 1) {
                    return;
                }

                headers.set(name, values.get(values.size() - 1));

            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }



}

上述是我跨域功能的代码,支持跨域功能及解决跨域冲突功能的问题。 上面有一个梗, exchange.getResponse().getHeaders()的header为只读,需要通过构造响应ServerHttpResponseDecorator 来解决只读的问题。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 自研网关:特殊URL功能的开发

    主要是通过过滤器对特殊的URL进行拦截,根据不同的情况来做判断,做跳转或异常抛出 具体代码大家可以去我的开源项目中看,欢迎提ISSUE及需求。 因为只有一个...

    星痕
  • activiti集成spring boot的一个怪问题

    最近想集成activti到spring boot中,上网找了一下例子,发现很简单,就开干了!

    星痕
  • JAVA单服务应用拆分成多个服务的实践(3)--前端的nginx转发

    上篇文章JAVA单服务应用拆分成多个服务的实践(2)--服务的dubbo化已经将部分模块微服务化了,但我们怎么测试? 我们的目标是支持ALL In One,又...

    星痕
  • 什么是SAP OData Model Creator

    The SAP OData Model Creator is a web site where your OData service metadata is t...

    Jerry Wang
  • 淘宝总裁为何是蒋凡?大数据功不可没

    【数据猿导读】 2017年12月27日,阿里巴巴集团在员工公开信中宣布,任命集团副总裁蒋凡出任淘宝总裁。 为何是年纪轻轻的蒋凡? 记者 | 小北 官网 | ww...

    数据猿
  • 传统软件转型云端 为何跳不出licsence怪圈?

    传企业软件走上云端,未来商业模式到底怎么走?最近 T哥也被多次问道,包括昨晚发布Oracle的文章的时候就有人提出质疑,连SAP,Oracle这样的IT巨头也曾...

    人称T客
  • hadoop中HDFS的NameNode原理

    老梁
  • C++ 动态链接库 DLL 的一些笔记

    Run-Time Check Failure #0 - The value of ESP was not properly saved across a fun...

    饶文津
  • 放弃手中Docker拥抱下一代容器管理工具Podman

    官网描述: Podman是一个无守护进程的容器引擎,用于在Linux系统上开发、管理和运行OCI容器(开源的容器管理工具)。容器可以作为根运行,也可以以无根模式...

    WeiyiGeek
  • 220亿次访问,5000万用户,腾讯健康码的诞生有着怎样的故事?

    2020年初,新冠肺炎疫情爆发,全民进入抗“疫”时期。腾讯作为一家科技互联网公司,也在积极思考能为抗击疫情做些什么。就在国家出台各种防疫政策,要求大家出入特定场...

    云大学小编

扫码关注云+社区

领取腾讯云代金券