filter 防xss 对 request数据进行修改

  这里采用了HttpServletRequestWrapper这个类,这个类是HttpServletRequest的包装类,对应的HttpServletResponseWrapper是HttpServletResponse的包装类。

首先,读取request里面的数据有三种形式

request.getParameter()
request.getInputStream()
request.getReader()

详情请查看  http://blog.csdn.net/clam_clam/article/details/6570539

如果可以通过getParameter()读取数据,那么可以用下面的方式进行xss的防御(request数据的修改)

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;

public class XSSRequestWrapper1 extends HttpServletRequestWrapper {
    public XSSRequestWrapper1(HttpServletRequest servletRequest) {
        super(servletRequest);
    }
    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        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);
        return stripXSS(value);
    }
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        return stripXSS(value);
    }
    
    private static String stripXSS(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            value = value.replaceAll("", "");
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e­xpression
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) e­xpressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e­xpression(...) e­xpressions
            scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... e­xpressions
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... e­xpressions
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= e­xpressions
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            value = value.replaceAll("<", "<").replaceAll(">", ">");
        }
        return value;
    }
}

  

如果可以通过getReader()读取数据,那么可以用下面的方式进行xss的防御(request数据的修改)

public class XSSRequestWrapper extends HttpServletRequestWrapper {

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

    /**
     * 用于保存读取body中数据
     */
    private final byte[] body;

    /**
     * 获取Body转换的JSON对象
     * @param request
     * @return
     */
    public static JSONObject getBodyJson(ServletRequest request) {
        JSONObject bodyJson;
        try {
            String bodyStr = getBodyStr(request);
            if(bodyStr!=null && bodyStr.replace(" ","").length()>0){
                bodyJson = JSONObject.fromObject(bodyStr);
            }else{
                bodyJson = new JSONObject();
            }

        } catch(Exception e) {
            bodyJson = new JSONObject();
            logger.error("getBodyJson error. ", e);
        }
        return bodyJson;
    }

    /**
     * 获取body字符串
     * @param request
     * @return
     */
    public static String getBodyStr(ServletRequest request) {
        String inputLine;
        StringBuffer buffer = new StringBuffer();
        try (BufferedReader br = request.getReader()) {
//            while ((inputLine = br.readLine()) != null) {
//                buffer.append(inputLine);
//            }
//findBug&codedex整改
            LineIterator lineIter = new LineIterator(br);
            while (lineIter.hasNext()) {
                buffer.append(lineIter.next());
            }
        } catch(Exception e) {
            logger.error("getBodyString error. ", e);
        }
        return buffer.toString();
    }

    public XSSRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        String bodyOld = getBodyStr(request);
        bodyOld = stripXSS(bodyOld);
        body = bodyOld.getBytes();
    }

    private static String stripXSS(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            value = value.replaceAll("", "");
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e­xpression
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) e­xpressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e­xpression(...) e­xpressions
            scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... e­xpressions
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... e­xpressions
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= e­xpressions
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            value = value.replaceAll("<", "<").replaceAll(">", ">");
        }
        return value;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        //1、因为流的读取是一次性的,所以,对流的方法进行重写
        //2、xss防御本身就要修改数据,然后将修改完成的数据从新放到request里面
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        
        return new ServletInputStream() {
            
            @Override
            public int read() throws IOException {
                return bais.read();
            }
            
            @Override
            public void setReadListener(ReadListener arg0) {
            }
            
            @Override
            public boolean isReady() {
                return false;
            }
            
            @Override
            public boolean isFinished() {
                return false;
            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}

 

posted on 2018-02-25 17:31  一个帅哥9527  阅读(489)  评论(0编辑  收藏  举报