自定义子类继承HttpServletRequestWrapper对Request参数编码
in JAVA编程安全 with 2 comments

自定义子类继承HttpServletRequestWrapper对Request参数编码

in JAVA编程安全 with 2 comments

有时候需要在Request请求到达Controller层之前进行修改,如防XSS攻击的HTML参数编码,通过Filter过滤器并自定义一个继承HttpServletRequestWrapper的子类可以完成将Request请求中参数逐一取出并定制编码修改后重新构造

java_HttpServletRequestWrapper_fiter.jpg

过滤器获取Request

Request请求到达Controller层之前进行修改,第一反应当然是在过滤器中进行处理
如果我们在Filter中使用request.getInputStream()获取流来得到body中的信息
可以达到将请求参数取出来的效果,但流的获取只能获取一次,之后再获取就获取不到了
这会导致controller无法拿到参数
因此采用自定义一个类继承HttpServletRequestWrapper
并将类处理后的内容封装为新的Request放在Filter的doFilter()方法中达到我们修改的诉求
比如防XSS攻击

重写getParameterValues()

自定义一个类继承HttpServletRequestWrapper,我们有很多方法均能够达到修改的目的
比如:重写getInputStream()创建新的流
本文主要使用的是重写getParameterValues()
使用该方法更为直观,可以更加自由的对传入的参数进行定制化的处理
getParameterValues()会将Request中所有的请求遍历,返回一个String的数组

package com.mebugs.request.utils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyCharRequestWrapper extends HttpServletRequestWrapper {

    public MyCharRequestWrapper(HttpServletRequest request) {
        super(request);
    }
    /**
     * 替换特殊符号与恶意脚本内容
     * @param parameter
     * @return
     */
    @Override
    public String[] getParameterValues(String parameter) {
        //原始Request请求参数数组
        String[] results = super.getParameterValues(parameter);
        if (results == null) {
            return null;
        }
        int count = results.length;
        //修改后全新Request请求参数数组
        String[] trimResults = new String[count];
        for (int i = 0; i < count; i++) {
            trimResults[i] = cleanXSS(results[i]); 
        }
        return trimResults;
    }
    //对字符串进行HTML编码操作
    private String cleanXSS(String value) {
        value = value.replaceAll("\"", "&quot;");
        value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
        value = value.replaceAll("'", "&#39;");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replaceAll("script", "");
        return value;
    }
}

Filter中的调用

doFilter中传入的是MyCharRequestWrapper(旧Request)构造
在创建对象过程中自动调用getParameterValues完成构造

package com.mebugs.request.utils;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyCharFilter implements Filter  {

    @Override
    public void destroy() {
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        //取用原始的Request
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp = (HttpServletResponse) response;
        //过滤后转为自定义的Request 
        //构造过程中会自动调用getParameterValues
        filterChain.doFilter(new MyCharRequestWrapper(req),rsp);
    }
    
    @Override
    public void init(FilterConfig arg0) throws ServletException {    
    }
}

web.xml配置过滤器

<filter>
    <filter-name>XssFilter</filter-name>
    <filter-class>com.mebugs.request.utils.MyCharFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>XssFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
Responses
  1. <filter> <filter-name>XssFilter</filter-name> <filter-class>com.mebugs.request.utils.MyCharFilter</filter-class> </filter> <filter-mapping> <filter-name>XssFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>

    Reply
    1. @米虫

      web.xml配置过滤器

      Reply