springboot清除字符串前后空格与防xss攻击方法
程序员文章站
2022-03-21 10:09:00
目录一、查看webmvcautoconfiguration.class中的方法源码三、创建webbindinginitializerconfiguration类springboot清除字符串前后空格与...
springboot清除字符串前后空格与防xss攻击
一、查看webmvcautoconfiguration.class中的方法源码
protected configurablewebbindinginitializer getconfigurablewebbindinginitializer() { try { //从容器中获取 return (configurablewebbindinginitializer)this.beanfactory.getbean(configurablewebbindinginitializer.class); } catch (nosuchbeandefinitionexception ex) { return super.getconfigurablewebbindinginitializer(); }
可以发现configurablewebbindinginitializer是从容器(beanfactory)中获取到的,所以我们可以配置一个
configurablewebbindinginitializer来替换默认的,只需要在容器中添加一个我们自定义的转换器即可。
当我们创建了自己的configurablewebbindinginitializer这个bean,spring boot就会自动使用它来配置spring mvc实现参数的类型转换。
二、自定义属性编辑器
/** * * @description 与spring mvc的@initbinder结合 用于防止xss攻击 */ class stringescapeeditor extends propertyeditorsupport { /** 转义html */ private boolean escapehtml; /** 转义javascript */ private boolean escapejavascript; /** 是否将空字符串转换为null */ private final boolean emptyasnull; /** 是否去掉前后空格 */ private final boolean trimmed; public stringescapeeditor() { this(true,true,false,true); } public stringescapeeditor(boolean escapehtml, boolean escapejavascript) { this(true,true,escapehtml,escapejavascript); } public stringescapeeditor(boolean emptyasnull,boolean trimmed, boolean escapehtml, boolean escapejavascript) { super(); this.emptyasnull = emptyasnull; this.trimmed = trimmed; this.escapehtml = escapehtml; this.escapejavascript = escapejavascript; } @override public string getastext() { object value = getvalue(); if(objects.nonnull(value)) { return value.tostring(); } return value != null ? value.tostring() : null; } @override public void setastext(string text) throws illegalargumentexception { string value = text; if (value == null || emptyasnull && text.isempty()) { //do nothing } else if (trimmed) { //去字符传参数前后空格 value = value.trim(); } if (escapehtml) { //html转义(防止xss攻击) //htmlutils.htmlescape 默认的是iso-8859-1编码格式,会将中文的某些符号进行转义。 //如果不想让中文符号进行转义请使用utf-8的编码格式。例如:htmlutils.htmlescape(text, "utf-8") value = htmlutils.htmlescape(value, "utf-8"); } if (escapejavascript) { //javascript转义(防止xss攻击) value = javascriptutils.javascriptescape(value); } setvalue(value); } }
三、创建webbindinginitializerconfiguration类
加上@bean注解,交给spring容器管理。
@configuration public class webbindinginitializerconfiguration { @bean public configurablewebbindinginitializer getconfigurablewebbindinginitializer() { configurablewebbindinginitializer initializer = new configurablewebbindinginitializer(); formattingconversionservice conversionservice = new defaultformattingconversionservice(); //we can add our custom converters and formatters //conversionservice.addconverter(...); //conversionservice.addformatter(...); initializer.setconversionservice(conversionservice); //we can set our custom validator //initializer.setvalidator(....); //here we are setting a custom propertyeditor initializer.setpropertyeditorregistrar(propertyeditorregistry -> { propertyeditorregistry.registercustomeditor(string.class, new stringescapeeditor()); }); return initializer; } }
springboot去除参数中前后空格说明
一、 需求
使用springboot使用过滤器去除@requestbody参数两端的空格;一般我们去普通的请求我们都会对请求参数进行验证。
java也提供了@notnull和@notblank这种验证方式,但是对@requestbody 这种只能验证是不是非空,对数据两端的空格未进行处理,同时大家也不想遍历一遍参数然后再处理再封装到对象中,正好项目中有这个需要,所以就参考别的做了post请求中针对application/json格式的有@requestbody注解的参数进行了去空格处理
二、 解决方法
2.1 新建一个过滤器
@component @webfilter(urlpatterns = "/**", filtername = "paramsfilter", dispatchertypes = dispatchertype.request) public class paramsfilter implements filter { @override public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { parameterrequestwrapper parmsrequest = new parameterrequestwrapper((httpservletrequest) request); chain.dofilter(parmsrequest, response); } @override public void init(filterconfig filterconfig) throws servletexception { } @override public void destroy() { } }
2.2 实现parameterrequestwrapper
import java.io.bytearrayinputstream; import java.io.ioexception; import java.util.arraylist; import java.util.hashmap; import java.util.iterator; import java.util.list; import java.util.map; import java.util.set; import javax.servlet.readlistener; import javax.servlet.servletinputstream; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletrequestwrapper; import com.alibaba.fastjson.jsonarray; import com.alibaba.fastjson.jsonobject; import org.apache.commons.io.ioutils; import org.apache.commons.lang3.stringutils; import org.springframework.http.httpheaders; import org.springframework.http.mediatype; import com.alibaba.fastjson.json; /** * @author : * @description * @date : 2021/4/22 */ public class parameterrequestwrapper extends httpservletrequestwrapper { private map<string , string[]> params = new hashmap<>(); public parameterrequestwrapper(httpservletrequest request) { super(request); map<string, string[]> requestmap=request.getparametermap(); this.params.putall(requestmap); this.modifyparametervalues(); } @override public servletinputstream getinputstream() throws ioexception { if(!super.getheader(httpheaders.content_type).equalsignorecase(mediatype.application_json_value)){ return super.getinputstream(); } string json = ioutils.tostring(super.getinputstream(), "utf-8"); if (stringutils.isempty(json)) { return super.getinputstream(); } map<string,object> map= jsonstringtomap(json); bytearrayinputstream bis = new bytearrayinputstream(json.tojsonstring(map).getbytes("utf-8")); return new myservletinputstream(bis); } public void modifyparametervalues(){ set<string> set = params.keyset(); iterator<string> it = set.iterator(); while(it.hasnext()){ string key= it.next(); string[] values = params.get(key); values[0] = values[0].trim(); params.put(key, values); } } @override public string getparameter(string name) { string[]values = params.get(name); if(values == null || values.length == 0) { return null; } return values[0]; } @override public string[] getparametervalues(string name) { return params.get(name); } class myservletinputstream extends servletinputstream { private bytearrayinputstream bis; public myservletinputstream(bytearrayinputstream bis){ this.bis=bis; } @override public boolean isfinished() { return true; } @override public boolean isready() { return true; } @override public void setreadlistener(readlistener listener) { } @override public int read(){ return bis.read(); } } public static map<string, object> jsonstringtomap(string jsonstring) { map<string, object> map = new hashmap<>(); jsonobject jsonobject = jsonobject.parseobject(jsonstring); for (object k : jsonobject.keyset()) { object o = jsonobject.get(k); if (o instanceof jsonarray) { list<map<string, object>> list = new arraylist<>(); iterator<object> it = ((jsonarray) o).iterator(); while (it.hasnext()) { object obj = it.next(); list.add(jsonstringtomap(obj.tostring())); } map.put(k.tostring(), list); } else if (o instanceof jsonobject) { map.put(k.tostring(), jsonstringtomap(o.tostring())); } else { if (o instanceof string) { map.put(k.tostring(), o.tostring().trim()); } else { map.put(k.tostring(), o); } } } return map; } }
三、 完美解决
参数前后空格完美去除!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。