springMVC 解决xss攻击

315 阅读1分钟
  • 问题
在url参数中或者post请求中携带JavaScript代码,比如携带alert(1) 
举例:url+/oa7/system/developer/manage?_=1649396422346&57555%22%3balert(1)%2f%2f609=1
错误:导致前端页面首先弹出弹出框
  • 解决:利用过滤器filter
    • 新建XssFilter类实现Filter接口
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 net.zdsoft.framework.utils.FilterParamUtils;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.Sets;

import java.io.IOException;
import java.util.Set;


public class XssFilter implements Filter {
   
   private  String[] notEscapeURI;
   private  String[] notEscapeParam;
   
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
       notEscapeURI = FilterParamUtils.getParamValues(filterConfig,
            "notEscapeURI");
       notEscapeParam = FilterParamUtils.getParamValues(filterConfig,
             "notEscapeParam");

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       boolean forceCheck = false;
       HttpServletRequest req = (HttpServletRequest) servletRequest;
       String uri = req.getRequestURI().trim();
       for(String s:notEscapeURI){
          if (StringUtils.contains(uri, s)) {
             forceCheck = true;
             break;
          }
       }
       if(forceCheck){
          filterChain.doFilter(servletRequest, servletResponse);
       }else{
          filterChain.doFilter(new XssHttpServletRequest(req,notEscapeParam), servletResponse);
       }
    }

    @Override
    public void destroy() {

    }
}
  • 新建XssHttpServletRequest类继承HttpServletRequestWrapper
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

import cn.hutool.http.HTMLFilter;
import org.apache.commons.lang3.StringEscapeUtils;

public class XssHttpServletRequest extends HttpServletRequestWrapper {
  private  Set<String> notEscapeParam;

   public XssHttpServletRequest(HttpServletRequest request,String[] notEscapeParam) {
       super(request);
       this.notEscapeParam = new HashSet<>(Arrays.asList(notEscapeParam));
   }

   @Override
   public String getHeader(String name) {
       return StringEscapeUtils.escapeHtml4(super.getHeader(name));
   }

   @Override
   public String getQueryString() {
       return StringEscapeUtils.escapeHtml4(super.getQueryString());
   }

   @Override
   public String getParameter(String name) {
       //return StringEscapeUtils.escapeHtml4(super.getParameter(name));
       return StringEscapeUtils.escapeHtml4(super.getParameter(xssEncode(name)));
   }

   @Override
   public String[] getParameterValues(String parameter) {
      if(notEscapeParam.contains(parameter)){//不想过滤的参数,此处content参数是 富文本内容
           return super.getParameterValues(parameter);
       }
       String[] values = super.getParameterValues(parameter);
       if (values == null) {
           return null;
       }
       return executeArray(values);
   }

   private String[] executeArray(String[] values) {
       int count = values.length;
       String[] encodedValues = new String[count];
       for (int i = 0; i < count; i++) {
           //encodedValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
           encodedValues[i] = StringEscapeUtils.escapeHtml4(xssEncode(values[i]));
       }
       return encodedValues;
   }

   @Override
   public Map<String, String[]> getParameterMap() {
       Map<String, String[]> map = super.getParameterMap();
       if (map == null || map.isEmpty()) {
           return map;
       }
       Map<String, String[]> newMap = new HashMap<>(map.size());
       for (Map.Entry<String, String[]> entry : map.entrySet()) {
           String[] values = entry.getValue();
           if (values == null) {
               newMap.put(entry.getKey(), entry.getValue());
           }
           else {
               newMap.put(entry.getKey(), executeArray(entry.getValue()));
           }
       }
       return newMap;
   }

   /**
    * 将容易引起xss漏洞的半角字符直接替换成全角字符
    *
    * @param s
    * @return
    */
   private static String xssEncode(String s) {
       if (s == null || s.isEmpty()) {
           return s;
       }
       try {
           HTMLFilter htmlFilter = new HTMLFilter();
           String name = htmlFilter.filter(s);

           return name;
       } catch (NullPointerException e) {
           return s;
       } catch (Exception ex) {
           ex.printStackTrace();
       }

       return null;
   }
}