spring mvc xss filter

来源:互联网 发布:snmp 端口 编辑:程序博客网 时间:2024/05/16 14:25

Spring MVC Xss Filter

       

       XSS (Cross Site Scripting): 跨站脚本攻击, 是Web程序中最常见的漏洞。指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的.  比如获取用户的Cookie,导航到恶意网站,携带木马等。

          一般现代应用MVC实现spring mvc的实现比较广泛,因此,本文章描述spring mvc 的实现xss filter。

第一步

        在web.xml中配置filter:

<!-- Xss-html-filter --><filter>        <filter-name>xssHttpServletFilter</filter-name>        <filter-class>com.x.y.filter.XssHttpServletFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>xssHttpServletFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>

第二步

        创建过滤器
import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.filter.OncePerRequestFilter;/** * 包装原生servlet对象,处理xss问题 *  */public class XssHttpServletFilter  extends OncePerRequestFilter {private static final Logger LOGGER = LoggerFactory.getLogger(XssHttpServletFilter.class);@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {try {XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);chain.doFilter(xssRequest, response);} catch (Exception e) {LOGGER.error("Xss过滤器,包装request对象失败");chain.doFilter(request, response);}}}


第三步

        创建request包装对象
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;/** * 请求包装对象 处理Xss */public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {HttpServletRequest orgRequest = null;public XssHttpServletRequestWrapper(HttpServletRequest request) {super(request);orgRequest = request;}/** * 覆盖getParameter方法,将参数名和参数值都做xss过滤 */@Overridepublic String getParameter(String name) {String value = super.getParameter(xssEncode(name));if (value != null) {value = xssEncode(value);}return value;}/** * 覆盖getParameterValues方法,将参数名和参数值都做xss过滤 */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] = xssEncode(values[i]);}return encodedValues;}/** * 获取request的属性时,做xss过滤 */ @Overridepublic Object getAttribute(String name) {Object value = super.getAttribute(name);if (null != value && value instanceof String) {value = xssEncode((String) value);}return value;};/** * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/> */@Overridepublic String getHeader(String name) {String value = super.getHeader(xssEncode(name));if (value != null) {value = xssEncode(value);}return value;}/** * 将容易引起xss漏洞的半角字符直接替换成全角字符 *  * @param s * @return */private static String xssEncode(String s) {if (s == null || s.isEmpty()) {return s;}try {HTMLFilter htmlFilter = new HTMLFilter();String clean = htmlFilter.filter(s);return clean;} catch (NullPointerException e) {return s;} catch (Exception ex) {ex.printStackTrace();}return null;}/** * 获取最原始的request *  * @return */public HttpServletRequest getOrgRequest() {return orgRequest;}/** * 获取最原始的request的静态方法 *  * @return */public static HttpServletRequest getOrgRequest(HttpServletRequest req) {if (req instanceof XssHttpServletRequestWrapper) {return ((XssHttpServletRequestWrapper) req).getOrgRequest();}return req;}}


第四步

        引用 html filter 的实现。采用htmlfitler 开源实现:xss-html-filter


关键点

Spring mvc 解析参数时,使用方法:webRequest.getParameterValues(name)获取参数,因此,request封装对象只有实现了getParameterValues(String parameter)方法,才会过滤到controller method 的入参。


Open Declaration Object org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
.resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception
         @Overrideprotected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);MultipartHttpServletRequest multipartRequest =WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);Object arg;if (MultipartFile.class.equals(parameter.getParameterType())) {assertIsMultipartRequest(servletRequest);Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");arg = multipartRequest.getFile(name);}else if (isMultipartFileCollection(parameter)) {assertIsMultipartRequest(servletRequest);Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");arg = multipartRequest.getFiles(name);}else if (isMultipartFileArray(parameter)) {assertIsMultipartRequest(servletRequest);Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");List<MultipartFile> multipartFiles = multipartRequest.getFiles(name);arg = multipartFiles.toArray(new MultipartFile[multipartFiles.size()]);}else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {assertIsMultipartRequest(servletRequest);arg = servletRequest.getPart(name);}else if (isPartCollection(parameter)) {assertIsMultipartRequest(servletRequest);arg = new ArrayList<Object>(servletRequest.getParts());}else if (isPartArray(parameter)) {assertIsMultipartRequest(servletRequest);arg = RequestPartResolver.resolvePart(servletRequest);}else {arg = null;if (multipartRequest != null) {List<MultipartFile> files = multipartRequest.getFiles(name);if (!files.isEmpty()) {arg = (files.size() == 1 ? files.get(0) : files);}}if (arg == null) {String[] paramValues = webRequest.getParameterValues(name);if (paramValues != null) {arg = paramValues.length == 1 ? paramValues[0] : paramValues;}}}return arg;}





0 0