欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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;
    }
}

三、 完美解决

springboot清除字符串前后空格与防xss攻击方法springboot清除字符串前后空格与防xss攻击方法

参数前后空格完美去除!

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