Request请求内容编码修改(偷懒) 与 XSS 叙述处理(滚蛋吧,脚本仔)

  对于在每个方法内部针对性的进行UTF - 8 字符编码的骚操作,已经烦乎其烦,不过确实等你烦的时候似乎就会有耐心去偷懒,好吧,进入正题。本文除了解决这个我看了一堆重复编码之后的代码之后,还有处理XSS攻击的方式,给自己留点速查的方式。

目录

       请求内容编码修改部分

1、事实证明这样CV根本不能偷懒(展示例子)

2、如果能一次修改,以后都不用CV多舒服

第一步,寻找源头实现

第二步,对其开刀整容

第三步,应用到项目中

       XSS应对


       请求内容编码修改部分

 

1、事实证明这样CV根本不能偷懒(展示例子)

           应该对如下处理请求获取文件名,参数的重复代码吧,如果只有一处两处,那还勉强可以,等项目膨胀起来后,这些东西就不是这么舒服了,甚至还有点皮,本身是可以避免的,换句话吧,本身我们是可以偷懒的,至于怎么偷懒,看下面

(1)

 fileName = URLEncoder.encode(fileName, "utf-8");

(2)
	OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");

(3)
    。。。

2、如果能一次修改,以后都不用CV多舒服

  如果我能直接从实现类上修改你说多舒服,那我们就找找,从这个输入流找起

第一步,寻找源头实现

 

至于上面两个包是引入的,我们目的是寻找servlet的实现,于是走进去第三个 ServletRequestWrapper 

public class ServletRequestWrapper implements ServletRequest 

显然并不是我们所需要的实现,再去 HttpServletRequest 目标类下方寻找,得到

再去查看Diagrams图谱,如果是IDEA的话,右键即可看到这个选项,eclipse的话我已经很久不用了,自行查阅吧,然后目标是实现类已经找到了,显然

 

第二步,对其开刀整容

    当然不可能在其源码内修改,come on men!

创建儿子 MultiReadHttpServletRequest ,重写该方法,当然还有其他 getReader()等

public class MultiReadHttpServletRequest {
    private String requestBody;

    //用于初始化时将body改编码
    public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        requestBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
    }

 @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8));
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return byteArrayInputStream.available() == 0;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

第三步,应用到项目中

    自定义过滤器,就叫ChatFilter

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        MultiReadHttpServletRequest request = new MultiReadHttpServletRequest((HttpServletRequest) req);
        String requestBody = request.getRequestBody();

        if (StringUtils.isNotEmpty(requestBody)) {
            request.setRequestBody(newRequestBody);
        }

        chain.doFilter(new XSSRequestWrapper(request), res);
    }

①如果是传统web项目,在web.xml 对应配置过滤器,其实本身传统项目也有引入的已经帮你弄好的 CharacterEncodingFilter 可以调用

②如果是springboot项目,在你所设置的配置类或者启动类下面,所谓的配置类,是

(@Configuration 注释的,且在启动类扫描baon包内的类) 
    @Bean
    public FilterRegistrationBean authFilterBean() {
        FilterRegistrationBean filterRegBean = new FilterRegistrationBean(new AuthFilter());
....
    }

 

 

  XSS应对

     其实具体说明,无需我再次说,xss即为跨站脚本攻击,详情百度说明。好吧,我安利一下吧 XSS的说明

归根到底都是脚本的问题,只需要对脚本进行阻隔就会有一定的抵御性,一个在数据解码过程中处理的问题需要应对。

       前端的处理预防部分,上门的超链接会有说明,这里我就不多指手画脚,让我们来谈谈后端的处理方式

     主要是对于脚本以及函数的替代与过滤,使其不能得到正确的编译与执行,从而使其失效的一种方式,主要还是可以通过过滤器来进行实现处理

public class XSSRequestWrapper extends HttpServletRequestWrapper {

    /**
     * Avoid anything between script tags
     */
    private static final Pattern scriptTagsPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);

    /**
     * Avoid anything in a src='...' type of expression
     */
    private static final Pattern scriptSrcPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    private static final Pattern scriptSrc2Pattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Remove any lonesome </script> tag
     */
    private static final Pattern scriptTagEndPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);

    /**
     * Remove any lonesome <script ...> tag
     */
    private static final Pattern scriptTagStartPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Avoid eval(...) expressions
     */
    private static final Pattern scriptEvalPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Avoid expression(...) expressions
     */
    private static final Pattern scriptExpressionPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Avoid javascript:... expressions
     */
    private static final Pattern scriptJavascriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);

    /**
     * Avoid vbscript:... expressions
     */
    private static final Pattern scriptVbscriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);

    /**
     * Avoid onload= expressions
     */
    private static final Pattern scriptOnloadPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

    /**
     * Replace <> tag
     */
    private static final Pattern scriptTagFlagPattern = Pattern.compile("[<>]", Pattern.CASE_INSENSITIVE);

    public XSSRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
    }

    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (allowedWithName(parameter)) {
            return values;
        }

        if (values == null) {
            return null;
        }

        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = stripXSS(values[i]);
        }

        return encodedValues;
    }

    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (allowedWithName(parameter)) {
            return value;
        }

        return stripXSS(value);
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (allowedWithName(name)) {
            return value;
        }

        return stripXSS(value);
    }

    public static boolean allowedWithName(String name){
        return name.endsWith("_content");
    }

    public static String stripXSS(String value) {
        if (value == null) {
            return value;
        }

        value = scriptTagsPattern.matcher(value).replaceAll("");
        value = scriptSrcPattern.matcher(value).replaceAll("");
        value = scriptSrc2Pattern.matcher(value).replaceAll("");
        value = scriptTagEndPattern.matcher(value).replaceAll("");
        value = scriptTagStartPattern.matcher(value).replaceAll("");
        value = scriptEvalPattern.matcher(value).replaceAll("");
        value = scriptExpressionPattern.matcher(value).replaceAll("");
        value = scriptJavascriptPattern.matcher(value).replaceAll("");
        value = scriptVbscriptPattern.matcher(value).replaceAll("");
        value = scriptOnloadPattern.matcher(value).replaceAll("");
        value = scriptTagFlagPattern.matcher(value).replaceAll("");
        return value;
    }
}

从请求头,参数上隔绝,就可以比较好地让大部分通用的脚本仔没有效果,为什么我说大部分,原因大家都懂,有时候你用IE 6 ,某些转义字符也可以zh转换成尖角,我能怎么办,当然是我懒,以为不存在用IE6的骨灰级玩家,总体而言,过滤器其实是一个好东西,没有错,总结完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值