SpringCloud微服务网关进行XSS攻击过滤-Zuul网关篇

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
通俗来说,在新增表单里,表单内容里插入一段html或者js代码,在列表渲染时就可能执行这串js代码。这就是xss攻击。

在微服务中,我们可以很方便的去网关中处理xss攻击,即自定义过滤器,在网关进行路径分发前进行输入数据的处理

直接编写自定义过滤器,继承ZuulFilter过滤器

package com.bp.getway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @author ZhuWeiHao
 * @date 2022/1/18
 * XSS过滤
 */
@Component
@Log4j2
public class XSSFilter extends ZuulFilter {


    //类型 pre,在之前处理
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    //Spring的排序,越小越早加载
    @Override
    public int filterOrder() {
        return -99;
    }

    //是否执行逻辑处理
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //过滤处理
    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String contentType = request.getContentType();
        if (StringUtils.isNotBlank(contentType)) {
            //表单和url提交方式
            if (StringUtils.equals(contentType, "application/x-www-form-urlencoded")
                    || StringUtils.equals(contentType, "application/x-www-form-urlencoded;charset=UTF-8")) {

                //对象引用不允许直接对原对象进行修改
                Map<String, String[]> parameterMap = new HashMap(request.getParameterMap());
                if (parameterMap == null || parameterMap.isEmpty()) {
                    return null;
                }
                Map<String, List<String>> requestQueryParams = requestContext.getRequestQueryParams();
                if (requestQueryParams == null) {
                    requestQueryParams = new HashMap<>(parameterMap.size() * 2);
                }
                Iterator<Map.Entry<String, String[]>> iterator = parameterMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, String[]> next = iterator.next();
                    List<String> list = Arrays.asList(next.getValue());
                    for (int i = 0; i < list.size(); i++) {
                        list.set(i, StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeHtml(list.get(i))));
                    }
                    String key = next.getKey();
                    requestQueryParams.put(key, list);
                }
                requestContext.setRequestQueryParams(requestQueryParams);
                //json提交方式
            } else if (StringUtils.equals(contentType, "application/json")
                    || StringUtils.equals(contentType, "application/json;charset=UTF-8")) {

                try {
                    InputStream in = requestContext.getRequest().getInputStream();
                    String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
                    JSONObject json = JSON.parseObject(body);
                    Map<String, Object> map = json;
                    Map<String, Object> mapJson = new HashMap<>();
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        mapJson.put(entry.getKey(), cleanXSS(entry.getValue().toString()));
                    }
                    String newBody = JSON.toJSONString(mapJson);
                    byte[] reqBodyBytes = newBody.getBytes();

                    //注意此处的HttpServletRequestWrapper 是java.servlet包下的
                    //重写输入流
                    requestContext.setRequest(new HttpServletRequestWrapper(request) {
                        @Override
                        public ServletInputStream getInputStream() {
                            return new ServletInputStreamWrapper(reqBodyBytes);
                        }

                        //注意此次两个获取内容长度方法一定要重写,不然容易造成读取长度不一致的问题
                        @Override
                        public int getContentLength() {
                            return reqBodyBytes.length;
                        }

                        @Override
                        public long getContentLengthLong() {
                            return reqBodyBytes.length;
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error("xss过滤器读取参数异常");
                }

            }


        }

        return null;
    }

    private String cleanXSS(String value) {
        if (StringUtils.isBlank(value)) {
            return value;
        }
        value = StringEscapeUtils.escapeHtml(value);
        value = StringEscapeUtils.escapeJavaScript(value);
        value = value.replaceAll("\\\\", "");
        return value;
    }

}

运行项目,进行输入测试,xss代码被转义了,效果达到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值