springboot抵御即跨站脚本(XSS)攻击

抵御即跨站脚本(XSS)攻击

XSS攻击通常指的是通过利用网站系统保存系统的漏洞,通过巧妙的方法把恶意指令注入到网页,用户加载网页的时候会自动执行恶意脚本

比如:

<script>
    alert(xss);
</script>

如果客户能在你的浏览器执行javascript,那么就能窃取cookie或者token。

1.pom.xml添加 依赖

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.14</version>
        </dependency>

可以查看hutool的知识点

HTML工具类-HtmlUtil · Hutool 参考文档

 

2.在自己的com.xxx.filter.xss包新建类XssHttpServletRequestWrapper

package com.xxxx.filter.xss;


public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 声明子类的构造器
     * @param request
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if(!StrUtil.hasEmpty(value)) {
            //把一些带script标签的 过滤掉,变成普通文本 HtmlUtil.filter 过滤HTML文本,防止XSS攻击
            value = HtmlUtil.filter(value);
        }
        //然后可以安全的保存到数据库里面的
        return value;
    }

    /**
     * 把返回的参数也进行转义
     * @param name
     * @return
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if(values != null){
            for (int i = 0;i < values.length; i++){
                String value = values[i];
                if(!StrUtil.hasEmpty(value)){
                    //把一些带script标签的 过滤掉,变成普通文本 HtmlUtil.filter 过滤HTML文本,防止XSS攻击
                    value = HtmlUtil.filter(value);
                }
                values[i] = value;
            }
        }
        //然后可以安全的保存到数据库里面的
        return values;
    }

    /**
     * 把请求中的数据返回一个map对象,也要做一下转义
     * @return
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> parameters = super.getParameterMap();
        LinkedHashMap<String, String[]> map = new LinkedHashMap();
        if(parameters!=null){
            for (String key:parameters.keySet()){
                String[] values=parameters.get(key);
                for (int i = 0; i < values.length; i++) {
                    String value = values[i];
                    if (!StrUtil.hasEmpty(value)) {
                        //HtmlUtil.filter 过滤HTML文本,防止XSS攻击
                        value = HtmlUtil.filter(value);
                    }
                    values[i] = value;
                }
                map.put(key,values);
            }
        }
        return map;
    }

    /**
     * 从请求头获取到数据 也要做一下转义
     * @param name
     * @return
     */
    @Override
    public String getHeader(String name) {
        String value= super.getHeader(name);
        if (!StrUtil.hasEmpty(value)) {
            //HtmlUtil.filter 过滤HTML文本,防止XSS攻击
            value = HtmlUtil.filter(value);
        }
        return value;
    }

    /**
     * 通过io流 读取数据 也要做一下转义
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        InputStream in= super.getInputStream();
        InputStreamReader reader=new InputStreamReader(in, Charset.forName("UTF-8"));
        BufferedReader buffer=new BufferedReader(reader);
        StringBuffer body=new StringBuffer();
        String line=buffer.readLine();
        while(line!=null){
            body.append(line);
            line=buffer.readLine();
        }
        buffer.close();
        reader.close();
        in.close();
        Map<String,Object> map=JSONUtil.parseObj(body.toString());
        Map<String,Object> result=new LinkedHashMap<>();
        for(String key:map.keySet()){
            Object val=map.get(key);
            if(val instanceof String){
                if(!StrUtil.hasEmpty(val.toString())){
                    //转义
                    result.put(key,HtmlUtil.filter(val.toString()));
                }
            }
            else {
                //不需要转义的数据
                result.put(key,val);
            }
        }
        //又转成json的字符串
        String json=JSONUtil.toJsonStr(result);
        ByteArrayInputStream bain=new ByteArrayInputStream(json.getBytes());
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bain.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

 3. 再建个XssFilter

package com.xxxx.filter.xss;

/**
 * urlPatterns = "/*"表示所有请求路由都需要拦截的
 */
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper(request);
        //通过后 继续往下执行 放行
        filterChain.doFilter(wrapper,servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

4. 最后一步是在启动文件里加上

@ServletComponentScan

  

5. 启动

6. 最后后端会把<script>标签过滤掉。

得出的结果是

alert(xxxxx);

7. 但是呢,同时也把html的标签也过滤掉了,我不想过滤掉html标签。

未完后续....

猜你喜欢

转载自blog.csdn.net/deng_zhihao692817/article/details/130615017
今日推荐