一、名词解释

XSS:跨站脚本攻击(Cross Site Scripting)

SQL注入:

click jacking(点击劫持)


二、java代码


1)过滤器

import java.io.IOException;

import java.util.HashSet;

import java.util.Set;


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 HttpSecurityFilter implements Filter {


private static final String X_FRAME_VALUE = "SAMEORIGIN";

    private static final String X_FRAME_HEADER = "X-FRAME-OPTIONS";

    public static final String FILTER_XSS_PARAM_NAME = "filter_xss";

    public static final String FILTER_SQL_INJECTION_PARAM_NAME = "filter_sql_injection";

    public static final String CLICK_JACKING_HEADER = "click_jacking_header";

    public static final String EXCLUSIONS_URI = "exclusions";

    boolean filterXSS = true;

    boolean filterSQL = true;

    boolean clickJacking = true;


    /**不拦截的地址*/

    private static Set<String> exclusions = new HashSet<String>();


    @Override

    public void init(FilterConfig config) throws ServletException {

        String filterXSSParam = config.getInitParameter(FILTER_XSS_PARAM_NAME);

        String filterSQLParam = config.getInitParameter(FILTER_SQL_INJECTION_PARAM_NAME);

        String clickJackingParam = config.getInitParameter(CLICK_JACKING_HEADER);

        filterXSS = new Boolean(filterXSSParam);

        filterSQL = new Boolean(filterSQLParam);

        clickJacking = new Boolean(clickJackingParam);

        readExclusion(config);

    }


    @Override

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;

        //获取uri

        String uri = req.getRequestURI();

        //排除不过滤的地址

        boolean isFilter = true;

        for (String exclusion : exclusions) {

            if (exclusion.trim().equals(uri.trim())) {

                isFilter = false;

                break;

            }

        }

        if (isFilter) {

        //请求信息中

            InjectionAttackWrapper wrapper = new InjectionAttackWrapper((HttpServletRequest) servletRequest, filterXSS,

                    filterSQL);

            //返回信息中

            filterClickJack(servletResponse);

            //过滤request、response

            filterChain.doFilter(wrapper, servletResponse);

        } else {

            filterChain.doFilter(req, servletResponse);

        }

    }


    @Override

    public void destroy() {}


    /**

     * 点击劫持处理

     * @param servletResponse

     */

    private void filterClickJack(ServletResponse servletResponse) {

        if (clickJacking) {

            if (servletResponse instanceof HttpServletResponse) {

                HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

                if (!httpServletResponse.containsHeader(X_FRAME_HEADER)) {

                    httpServletResponse.addHeader(X_FRAME_HEADER, X_FRAME_VALUE);

                }

            }

        }

    }


    /**

     * 排除不过滤的地址

     * @param config

     */

    private void readExclusion(FilterConfig config) {

        //不过滤的地址

        String exclusion = config.getInitParameter(EXCLUSIONS_URI);

        if (exclusion == null || exclusion.trim().equals("")) {

            return;

        }

        String[] exclusionArray = exclusion.split(",");

        for (String uri : exclusionArray) {

            exclusions.add(uri);

        }

    }


}


2)请求信息中具体匹配规则(正则匹配)


import java.util.HashMap;

import java.util.Map;

import java.util.Set;


import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;


public class InjectionAttackWrapper extends HttpServletRequestWrapper {

    ​private static final String EVENTS = "((?i)onload|onunload|onchange|onsubmit|onreset"

            + "|onselect|onblur|onfocus|onkeydown|onkeypress|onkeyup"

            + "|onclick|ondblclick|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup)";


    private static final String XSS_HTML_TAG = "(%3C)|(%3E)|[<>]+";

    private static final String XSS_INJECTION = "((%22%20)|(%22\\s)|('%22)|(%22\\+))\\w.*|(\\s|%20)" + EVENTS

            + ".*|(%3D)|(%7C)";

    private static final String XSS_REGEX = XSS_HTML_TAG + "|" + XSS_INJECTION;

    private static final String SQL_REGEX = "('.+--)|(--)|(%7C)|"+"(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";


    boolean filterXSS = true;

    boolean filterSQL = true;


    public InjectionAttackWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {

        super(request);

        this.filterXSS = filterXSS;

        this.filterSQL = filterSQL;

    }


    public InjectionAttackWrapper(HttpServletRequest request) {

        this(request, true, true);

    }


    @Override

    public String getParameter(String name) {

        String value = super.getParameter(name);

        return filterParamString(value);

    }


    @SuppressWarnings("unchecked")

    @Override

    public Map<String, String[]> getParameterMap() {

        Map<String, String[]> rawMap = super.getParameterMap();

        Map<String, String[]> filteredMap = new HashMap<String, String[]>(rawMap.size());

        Set<String> keys = rawMap.keySet();

        for (String key : keys) {

            String[] rawValue = rawMap.get(key);

            String[] filteredValue = filterStringArray(rawValue);

            filteredMap.put(key, filteredValue);

        }

        return filteredMap;

    }


    protected String[] filterStringArray(String[] rawValue) {

        String[] filteredArray = new String[rawValue.length];

        for (int i = 0; i < rawValue.length; i++) {

            filteredArray[i] = filterParamString(rawValue[i]);

        }

        return filteredArray;

    }


    @Override

    public String[] getParameterValues(String name) {

        String[] rawValues = super.getParameterValues(name);

        if (rawValues == null)

            return null;

        String[] filteredValues = new String[rawValues.length];

        for (int i = 0; i < rawValues.length; i++) {

            filteredValues[i] = filterParamString(rawValues[i]);

        }

        return filteredValues;

    }


    protected String filterParamString(String rawValue) {

        if (rawValue == null) {

            return null;

        }

        if (filterXSS()) {

           ​ rawValue = rawValue.replaceAll(XSS_REGEX, "");

        }

        if (filterSQL()) {

           ​ rawValue = rawValue.replaceAll(SQL_REGEX, "");

        }

        return rawValue;

    }


    @Override

    public Cookie[] getCookies() {

        Cookie[] existingCookies = super.getCookies();

        if (existingCookies != null) {

            for (int i = 0; i < existingCookies.length; ++i) {

                Cookie cookie = existingCookies[i];

                cookie.setValue(filterParamString(cookie.getValue()));

            }

        }

        return existingCookies;

    }


    @Override

    public String getQueryString() {

        return filterParamString(super.getQueryString());

    }


    protected boolean filterXSS() {

        return filterXSS;

    }


    protected boolean filterSQL() {

        return filterSQL;

    }


}


三、web.xml文件


<filter>

<filter-name>xss_sql_clickjacking_filter</filter-name>

<filter-class>com.xxx.utils.HttpSecurityFilter</filter-class>


<init-param>

<param-name>filter_xss</param-name>

<param-value>true</param-value>

</init-param>

<init-param>

<param-name>filter_sql_injection</param-name>

<param-value>true</param-value>

</init-param>

<init-param>

<param-name>click_jacking_header</param-name>

<param-value>false</param-value>

</init-param>

</filter>


<filter-mapping>

<filter-name>xss_sql_clickjacking_filter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>