SpringBoot integrates Hutool to prevent XSS attacks

Table of contents

definition

Solution

The idea is as follows: 

A definition filter XssFillter inherits Fillter to intercept http requests

Second, use the tool class to inherit HttpServletRequestWrapper for request escaping

Three configuration startup classes

Four control layers

test


definition

XSS is an abbreviation for Cross Site Scripting. The xss attack method is to run when the user uses the browser, and steal user information (such as cookies, etc.) by embedding scripts. Harder to spot than phishing sites, usually implemented with JavaScript.

Solution

  •  Front-end settings, such as using vue to set httponly
  •  The back-end http request performs an escape operation ( this is mainly introduced here

The idea is as follows:
 a definition filter XssFillter inherits Fillter to intercept http requests

package com.example.wechatdemo.config.xss;
 
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
//拦截请求
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @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() {
 
    }
}

Second, use the tool class to inherit  HttpServletRequestWrapper for request escaping

 The inheritance system of HttpServletRquestWrapper is as shown in the figure below. The tool class inherits HttpServletRequestWrapper and overrides getParameterNames, getParameter, getParameterValues ​​and other methods to simply perform http request escaping

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONUtil;
 
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.Map;
//思路是使用 HttpServletRequestWrapper 实现后端
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }
    //提取请求参数
    @Override
    public String getParameter(String name) {
        String value= super.getParameter(name);
        if(!StrUtil.hasEmpty(value)){
            value=HtmlUtil.filter(value);
        }
        return value;
    }
 
    @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)){
                    value=HtmlUtil.filter(value);
                }
                values[i]=value;
            }
        }
        return values;
    }
 
    //转义数据
    @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)) {
                        //导入Hutool的依赖,进行html转义
                        value = HtmlUtil.filter(value);
                    }
                    values[i] = value;
                }
                map.put(key,values);
            }
        }
        return map;
    }
 
    @Override
    public String getHeader(String name) {
        String value= super.getHeader(name);
        if (!StrUtil.hasEmpty(value)) {
            value = HtmlUtil.filter(value);
        }
        return value;
    }
 
    @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);
            }
        }
        String json=JSONUtil.toJsonStr(result);
        ByteArrayInputStream bain=new ByteArrayInputStream(json.getBytes());
        //匿名类实现IO流
        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) {
 
            }
        };
    }
}

Three configuration startup classes

The startup class should enable servlet scanning


@SpringBootApplication
@EnableScheduling 
@ServletComponentScan
public class SpringBootBaseApplication {

	public static void main(String[] args) throws IOException {
		SpringApplication.run(SpringBootBaseApplication.class, args);
	}


}

 Four control layers

import com.example.wechatdemo.common.util.R;
import com.example.wechatdemo.controller.form.TestFrom;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
 
import javax.validation.Valid;
 
@RestController
@RequestMapping
@Api("测试web接口")
public class TestController {
    @PostMapping("/sayhello")
    @ApiOperation("简单的测试方法")
    public R sayHello(@Valid @RequestBody TestFrom testFrom){
        return R.ok().put("message",testFrom.getName());
 
    }
}

test

The screenshot of the swagger2 test is as follows

Guess you like

Origin blog.csdn.net/qq_39706515/article/details/130146029