使用springMVC通过Filter实现防止xss注入

 更新时间:2021年07月07日 15:18:39   作者:归田  
这篇文章主要介绍了使用springMVC通过Filter实现防止xss注入的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

springMVC Filter防止xss注入

跨站脚本工具(cross 斯特scripting),为不和层叠样式表(cascading style sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。

恶意攻击者往web页面里插入恶意scriptScript代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

防止XSS攻击简单的预防就是对Request请求中的一些参数去掉一些比较敏感的脚本命令。

原本是打算通过springMVC的HandlerInterceptor机制来实现的,通过获取request然后对request中的参数进行修改,结果虽然值修改了,但在Controller中获取的数值还是没有修改的。没办法就是要Filter来完成。

简单来说就是创建一个新的httpRequest类XsslHttpServletRequestWrapper,然后重写一些get方法(获取参数时对参数进行XSS判断预防)。

@WebFilter(filterName="xssMyfilter",urlPatterns="/*") 
public class MyXssFilter implements Filter{ 
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {		
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	        throws IOException, ServletException {
		XsslHttpServletRequestWrapper xssRequest = new XsslHttpServletRequestWrapper((HttpServletRequest)request);
		chain.doFilter(xssRequest , response); 
	}
	
	@Override
	public void destroy() {		
	}	
}

XSS代码的过滤是在XsslHttpServletRequestWrapper中实现的,主要是覆盖实现了getParameter,getParameterValues,getHeader这几个方法,然后对获取的value值进行XSS处理。

public class XsslHttpServletRequestWrapper extends HttpServletRequestWrapper { 
  HttpServletRequest xssRequest = null;  
 public XsslHttpServletRequestWrapper(HttpServletRequest request) {
  super(request);
  xssRequest = request;
 } 
 
  @Override  
  public String getParameter(String name) {  
       String value = super.getParameter(replaceXSS(name));  
         if (value != null) {  
             value = replaceXSS(value);  
         }  
         return value;  
  }  
  
  @Override
 public String[] getParameterValues(String name) {
   String[] values = super.getParameterValues(replaceXSS(name));
   if(values != null && values.length > 0){
    for(int i =0; i< values.length ;i++){
     values[i] = replaceXSS(values[i]);
    }
   }
  return values;
  }
  
  @Override  
  public String getHeader(String name) {  
   
         String value = super.getHeader(replaceXSS(name));  
         if (value != null) {  
             value = replaceXSS(value);  
         }  
         return value;  
     } 
  /**
   * 去除待带script、src的语句,转义替换后的value值
   */
 public static String replaceXSS(String value) {
     if (value != null) {
         try{
          value = value.replace("+","%2B");   //'+' replace to '%2B'
          value = URLDecoder.decode(value, "utf-8");
         }catch(UnsupportedEncodingException e){
         }catch(IllegalArgumentException e){
     }
         
   // Avoid null characters
   value = value.replaceAll("\0", "");
 
   // Avoid anything between script tags
   Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
 
   // Avoid anything in a src='...' 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 alert:... e­xpressions
   scriptPattern = Pattern.compile("alert", Pattern.CASE_INSENSITIVE);
   value = scriptPattern.matcher(value).replaceAll("");
   // Avoid οnlοad= e­xpressions
   scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
   value = scriptPattern.matcher(value).replaceAll("");
   scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);  
   value = scriptPattern.matcher(value).replaceAll("");
  }         
     return filter(value);
 }  
  /**
   * 过滤特殊字符
   */
  public static String filter(String value) {
         if (value == null) {
             return null;
         }        
         StringBuffer result = new StringBuffer(value.length());
         for (int i=0; i<value.length(); ++i) {
             switch (value.charAt(i)) {
              case '<':
                  result.append("<");
                  break;
              case '>': 
                  result.append(">");
                  break;
              case '"': 
                  result.append(""");
                  break;
              case '\'': 
                  result.append("'");
                  break;
              case '%': 
                  result.append("%");
                  break;
              case ';': 
                  result.append(";");
                  break;
           case '(': 
                  result.append("(");
                  break;
              case ')': 
                  result.append(")");
                  break;
              case '&': 
                  result.append("&");
                  break;
              case '+':
                  result.append("+");
                  break;
              default:
                  result.append(value.charAt(i));
                  break;
          }  
         }
         return result.toString();
     } 
}

SpringMVC 防止XSS 工具(常规方式)

要求:

xss过滤请求的参数:Content-Type为 json(application/json)

SpringMVC 对于application/json 转换处理说明:

spring mvc默认使用MappingJackson2HttpMessageConverter转换器,

而它是使用jackson来序列化对象的,如果我们能 将jackson的序列化和反序列化过程修改,加入过滤xss代码,并将其注册到MappingJackson2HttpMessageConverter中

具体实现功能代码:

import java.io.IOException;
import org.apache.commons.text.StringEscapeUtils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 
/**
 * 反序列化
 *
 */
public class XssDefaultJsonDeserializer extends StdDeserializer<String> { 
 public XssDefaultJsonDeserializer(){
  this(null);
 }
 
 public XssDefaultJsonDeserializer(Class<String> vc) {
  super(vc);
 }
 
 @Override
 public String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  // TODO Auto-generated method stub
  //return StringEscapeUtils.escapeEcmaScript(jsonParser.getText());
  return StringEscapeUtils.unescapeHtml4(jsonParser.getText());
 } 
}

SpringMVC 配置对象:

@Configuration
@EnableWebMvc
public class SpingMVCConfig extends WebMvcConfigurerAdapter {
 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  super.configureMessageConverters(converters);
  // TODO Auto-generated method stub
  SimpleModule module = new SimpleModule();
  // 反序列化
  module.addDeserializer(String.class, new XssDefaultJsonDeserializer());
  // 序列化
  module.addSerializer(String.class, new XssDefaultJsonSerializer());
  ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().build();
  // 注册自定义的序列化和反序列化器
  mapper.registerModule(module);
  MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
  converters.add(converter);
          }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 将springboot项目生成可依赖的jar并引入到项目中的方法

    将springboot项目生成可依赖的jar并引入到项目中的方法

    SpringBoot项目默认打包的是可运行jar包,也可以打包成不可运行的jar包,本文给大家介绍将springboot项目生成可依赖的jar并引入到项目中的方法,感兴趣的朋友一起看看吧
    2023-11-11
  • IntelliJ IDEA 使用经验总结(推荐)

    IntelliJ IDEA 使用经验总结(推荐)

    这篇文章主要介绍了IntelliJ IDEA 使用经验总结,非常不错,具有参考价值,需要的朋友可以参考下
    2018-02-02
  • SpringBoot应用部署到外置Tomcat的实现

    SpringBoot应用部署到外置Tomcat的实现

    SpringBoot内置tomcat使用很方便,本文主要介绍了SpringBoot应用部署到外置Tomcat的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-07-07
  • 在Spring中如何处理循环依赖问题

    在Spring中如何处理循环依赖问题

    Spring解决循环依赖的关键在于提前曝光未完全创建的bean,在Spring中创建Bean分为实例化、属性填充和初始化三步,循环依赖的解决思路是先创建A的bean实例,此时A是不完整的,用一个Map保存不完整的A,再创建B,B需要注入A
    2025-01-01
  • Java冒泡排序简单实现

    Java冒泡排序简单实现

    这篇文章主要介绍了Java冒泡排序简单实现,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 详解spring项目中如何动态刷新bean

    详解spring项目中如何动态刷新bean

    这篇文章主要为大家介绍了详解spring项目中如何动态刷新bean,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Java实现的简单画图板示例

    Java实现的简单画图板示例

    这篇文章主要介绍了Java实现的简单画图板,涉及java使用swing组件进行图形绘制相关操作技巧,需要的朋友可以参考下
    2018-08-08
  • Java 实战范例之进销存管理系统的实现

    Java 实战范例之进销存管理系统的实现

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+vue+Springboot+ssm+mysql+maven+redis实现一个前后端分离的进销存管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • java.lang.Void类源码解析

    java.lang.Void类源码解析

    这篇文章主要介绍了java.lang.Void类源码解析的相关内容,对源码中的部分内容进行解释,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • Java 注解@PostConstruct的原理及使用场景

    Java 注解@PostConstruct的原理及使用场景

    @PostConstruct 是 Java 中用于标记初始化方法的注解,本文将详细讲解 @PostConstruct 的原理、使用场景及最佳实践,感兴趣的朋友一起看看吧
    2025-04-04

最新评论