记录网关zuul处理跨域/XSS问题

news2024/11/25 10:54:46

一,疑问

1.之前遇到跨域问题是在NG中解决的,添加跨域请求头和域名配置。那么与网关处理跨域问题关系是什么,NG处理了,为什么还需要在网关中处理

二,前置知识

zuul概念与原理

zuul 的概念和原理 - 知乎

Zuul工作原理_zuul原理_吴声子夜歌的博客-CSDN博客

梳理几个基本概念

zuul的工作原理
1.过滤器机制
zuul的核心是一系列的filters, 其作用可以类比Servlet框架的Filter,或者AOP。
zuul把Request route到 用户处理逻辑 的过程中,这些filter参与一些过滤处理,比如Authentication,Load Shedding等

2.过滤器机制过滤器类型
Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
(1) PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
(2) ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
(3) POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
(4) ERROR:在其他阶段发生错误时执行该过滤器

总结:通过一个个过滤器实现不同的业务逻辑,且不同过滤器类型按照顺序执行对应的业务

三,此文网关做了那几件事

1.PRE,前置需要处理的逻辑,跨域/XSS处理

2.POST,微服务处理之后记录处理时间等日志信息

具体处理逻辑

1.跨域问题重现,前端报错,如下包含了请求源Origin信息

 

 2. ZuulFilter1跨域/xss攻击代码

Component
@RefreshScope
public class TimeCostPreFilter extends ZuulFilter {
    public static final String START_TIME_KEY = "start_time";
    public static final String ZUUL_REQUEST_URL_KEY = "zuul_request_start_time";

    private static final Logger logger = LoggerFactory.getLogger(TimeCostPreFilter.class);

    @Value("${com.gateway.xss.check:true}")
    private Boolean xssCheck;

    @Value("${com.gateway.xss.url.filter:uploadFile,uploadImage}")
    private String urlFilter;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 判断是否要拦截的逻辑
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {

        long startTime = System.currentTimeMillis();
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();

        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String nextElement = headerNames.nextElement();
                if (nextElement.equalsIgnoreCase("origin") && request.getHeader(nextElement) != null) {
                    String str = request.getHeader(nextElement).toLowerCase();
                    String pattern = "^(http|https)://(.*\\.skcloud\\.cn|.*\\.skcloud\\.com|.*\\.sk\\.com|localhost:?[0-9]*|api.rrx.cn|c2bt4.skcloud.com)$";

                    Pattern r = Pattern.compile(pattern);
                    Matcher m = r.matcher(str);
                    if (!m.matches()) {
                        return null;
                    }
                }
            }
        }

        StringBuffer requestUrl = request.getRequestURL();
        String url = requestUrl.toString();
        if (xssCheck) {
            if (!StringUtils.isEmpty(urlFilter)) {
                String[] urlFilterList = urlFilter.split(",");
                for (String s : urlFilterList) {
                    if (!StringUtils.isEmpty(urlFilter) && url.contains(s)) {
                        currentContext.set(ZUUL_REQUEST_URL_KEY, url);
                        currentContext.set(START_TIME_KEY, startTime);
                        return null;
                    }
                }
            }
            try {
                Map<String, String[]> map = request.getParameterMap();
                if (!(Objects.isNull(map) || map.isEmpty())) {
                    for (Map.Entry<String, String[]> entry : map.entrySet()) {
                        String[] value = entry.getValue();
                        if (extracted(currentContext, value[0])) {
                            return null;
                        }
                    }
                }
                InputStream in = request.getInputStream();
                String body = StreamUtils.copyToString(in, StandardCharsets.UTF_8);
                if (!StringUtils.isEmpty(body)) {
                    if (extracted(currentContext, body)) {
                        return null;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        currentContext.set(ZUUL_REQUEST_URL_KEY, url);
        currentContext.set(START_TIME_KEY, startTime);
        return null;
    }

    private static boolean extracted(RequestContext currentContext, String body) {
        boolean b = checkXss(body);
        if (b) {
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseBody("非法请求");
            currentContext.setResponseStatusCode(HttpStatus.BAD_REQUEST.value());
            return true;
        }
        return false;
    }

    public static boolean checkXss(String str) {
        if (StringUtils.isEmpty(str)) {
            return false;
        }
        boolean contains = str.contains("<");
        boolean contains1 = str.contains(">");
        boolean onclick = str.contains("onclick");
        return contains || contains1 || onclick;
    }

3. ZuulFilter2,日志记录

@Component
@RefreshScope
public class TimeCostPostFilter extends ZuulFilter {
    private static final String START_TIME_KE = "start_time";
    public static final String ZUUL_REQUEST_URL_KEY = "zuul_request_start_time";

    private static final Logger logger = LoggerFactory.getLogger(TimeCostPostFilter.class);

    @Autowired
    private GateWayRequestTimeClient gateWayRequestTimeClient;

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        String requestUrl = (String) currentContext.get(ZUUL_REQUEST_URL_KEY);
        long startTime = (long) currentContext.get(START_TIME_KE);
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        int responseStatusCode = currentContext.getResponseStatusCode();
        gateWayRequestTimeClient.insertLog(startTime, endTime, resultTime, requestUrl, responseStatusCode);
        return null;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/424305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

接触过的第一台电脑-90年代的x86与如今的树莓派

#勤写标兵挑战赛#最早接触电脑是在幼儿园&#xff0c;那时候电脑下象棋都要输入命令行的。后来小学时候有了电脑课&#xff0c;要穿鞋套的。满满的回忆。那个时代电子产品更新很慢的&#xff0c;一台电脑可以用5年&#xff0c;286-386-486-586。486电脑的特点是&#xff1a;处理…

python数据分析-matplotlib散点图-条形图的绘制以及完整方法归纳02

matplotlib的基本使用02一.散点图的绘制二.散点图绘图步骤及案例解析1.导入模块2.设置散点图所有字符的字体样式3.编写主体代码4.主题代码解析5.图形展示三.条形图的绘制四.条形图案例展示1.导入模块五.绘制条形图完整代码六.条形图展示七.多个条形图展示1.结果展示八.总结一.散…

工业交换机与商业交换机区别对比

摘要&#xff1a;工业交换机和商业交换机在功能方面差距较小&#xff0c;性能方面差别很大。最主要的差别是在对各类环境的适应性上&#xff0c;包括在温度、湿度、盐雾环境、振动环境、恶劣电磁干扰环境、海拔等各类环境下稳定可靠提供功能服务的能力。当然工业交换机在一些告…

Word控件Spire.Doc for .net 功能详解

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

继续Stable-Diffusion WEBUI方方面面研究(内容索引)

文章目录&#xff08;零&#xff09;前言&#xff08;一&#xff09;绘图&#xff08;1.1&#xff09;模型&#xff08;1.1.1&#xff09;基础模型&#xff08;Stable-diffusion模型&#xff09;&#xff08;1.1.2&#xff09;人物模型&#xff08;LoRA模型&#xff09;&#x…

4.4、网络模型

4.4、网络模型1.OSI七层参考模型2.TCP/IP四层模型①简介②四层介绍1.OSI七层参考模型 七层模型&#xff0c;亦称 OSI&#xff08;Open System Interconnection&#xff09;参考模型&#xff0c;即开放式系统互联。参考模型是国际标准化组织&#xff08;ISO&#xff09;制定的一…

实验1 MATLAB环境与运算基础

实验一一、实验的目的与要求二、实验原理三、实验仪器四、实验内容与步骤五、实验分析与总结一、实验的目的与要求 1、掌握 MATLAB环境与基本操作&#xff1b; 2、掌握 MATLAB常见数据类型的创建、表示和引用&#xff1b; 3、熟悉 MATLAB数据类型的各种运算与常用函数&#xf…

一篇文章让你搞懂TypeScript中的typeof()、keyof()是什么意思

TypeScript中的typeof&#xff08;&#xff09;、keyof&#xff08;&#xff09;是什么意思&#xff1f;知识回调&#xff08;不懂就看这儿&#xff01;&#xff09;场景复现核心干货&#x1f447;&#x1f447;&#x1f447;举例引入字面量类型&#xff08;literal types&…

AC7811电机驱动方案—电路分析

目录 电源树 12V转5V 输出电压设计 电感的选取 欠压锁定 电容的选取 PCB布局 5V转3.3V 输出噪声 外部反向电压保护 接口电路设计 USB转串口 JTAG 驱动电路 驱动桥电路 采样回路设计 电源树 12V转5V 使用了MPQ4420作为电压转换芯片。 芯片手册经典应用 输出电…

Kafka——概述、安装及命令行操作

文章目录一、概述1.1、定义1.2、如何运作&#xff1f;1.3、传统消息队列的应用场景1.4、消息队列的两种模式1.5、Kafka的基础架构二、安装&#xff08;需要安装zookeeper&#xff09;三、常用命令行操作3.1、主题命令行操作3.2、生产者命令行操作3.3、消费者命令行操作一、概述…

Python操作MySQL就是这么简单

Python操作MySQL就是这么简单下载MySQL 8.0安装MySQL 8.0步骤2&#xff1a;选择安装类型步骤3&#xff1a;选择安装位置步骤4&#xff1a;配置MySQL 8.0步骤5&#xff1a;安装MySQL 8.0步骤6&#xff1a;完成安装启动MySQL 8.0MySQL 8.0的常用命令python的 pymysql库操作方法安…

【C++】哈希的应用 -- 位图

文章目录一、位图的引入二、位图的实现三、bitset四、位图的应用五、哈希切割一、位图的引入 我们通过一道面试题来引入位图&#xff1a; 给定40亿个不重复的无符号整数&#xff0c;且没排过序&#xff0c;现在给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数…

ChatGPT想干掉测试人员,做梦去吧

很多人都发现ChatGPT可以做一些代码相关的工作&#xff0c;不仅可以写一些测试用例和自动化脚本&#xff0c;还可以做一定量的调优&#xff0c;于是就开始担忧起来&#xff0c;到哪天我的测试工作会不会被ChatGPT这个工具给取代了&#xff1f; 1. ChatGPT目前对哪些东西会有冲击…

Java:Arrays类

1、Arrays是啥&#xff1f; 数组操作工具类&#xff0c;专门用于操作数组元素的。 2.Arrays类的常用API 方法说明public static String toString(类型[] a)对数组进行排序public static void sort(类型[] a)对数组进行默认升序排序public static <T> void sort(类型[]…

图像分割——交叉熵损失

一、前言 写这篇博客的目的主要有两点&#xff0c;首先一点就是&#xff0c;以为对于交叉熵学过就会了&#xff0c;当初笔记也没有详细写过&#xff0c;但今天看论文发现里面的公式没有看懂才发现自己了解的还不够&#xff0c;平时用也是直接用的框架&#xff0c;原来一直认为会…

Java基础--数据结构

阅读目录 目录 数据结构 Java 集合框架 List Set Map 数据结构 Java工具包提供了强大的数据结构。在Java中的数据结构主要包括以下几种接口和类&#xff1a; 枚举&#xff08;Enumeration&#xff09;、位集合&#xff08;BitSet&#xff09;、向量&#xff08;Vector&a…

进阶C语言:程序环境和预处理

有关C语言的知识马上就要结束了&#xff0c;在学完了前面的基础之上我们就来深究一下程序底层的逻辑&#xff0c;关于程序的预处理编译指令&#xff0c;话不多说&#xff0c;我们直接开始&#xff1a; 目录 1.程序的翻译环境和执行环境 2. 详解编译链接 2.1翻译环境 2.2编译…

IT培训有靠谱的机构吗,长什么样的?

关于IT培训的问题&#xff0c;网上有一大波劝退的声音&#xff1a;现在的IT越来越卷&#xff0c;高校计算机专业毕业生每年那么多&#xff0c;作为小白转行的你竞争力又在哪里呢&#xff1f;而且去年互联网大厂那么多裁员&#xff0c;还有大幅度降薪等等&#xff0c;IT行业已经…

通达信破底翻选股公式,用缠论底分型进行优化

上次在写《通达信破底翻形态选股公式&#xff0c;选出破底之后再翻回的股票》这篇文章时&#xff0c;编写破底翻选股公式就考虑使用缠论底分型&#xff0c;但是底分型的包含关系较为复杂&#xff0c;不容易处理&#xff0c;只能暂时搁置&#xff0c;采用了一种简单的方式&#…

【PyTorch】第九节:Softmax 函数与交叉熵函数

作者&#x1f575;️‍♂️&#xff1a;让机器理解语言か 专栏&#x1f387;&#xff1a;PyTorch 描述&#x1f3a8;&#xff1a;PyTorch 是一个基于 Torch 的 Python 开源机器学习库。 寄语&#x1f493;&#xff1a;&#x1f43e;没有白走的路&#xff0c;每一步都算数&#…