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("
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();
} 
}
", ""); // 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);
          }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。