The backend defends against XSS attacks, using the inherited HttpServletRequestWrapper to escape the content of the request

1. Import dependent libraries
Because the Hutool toolkit has tools for XSS escaping, we need to import Hutool, and then use the
request wrapper class provided by the Servlet specification to define the data escaping function.
Import maven dependencies

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

Two, implement the code

The HttpServletRequest we usually encounter when writing web projects is actually an interface. If we want to redefine the request
class, extending this interface is the last thing to do. Because there are too many abstract methods in the HttpServletRequest interface, it
is too time-consuming for us to implement them one by one. So we should choose a simpler way to customize the request class. That is to inherit
the HttpServletRequestWrapper parent class.
JavaEE is just a standard, and the specific implementation is done by various application server vendors. For example, when Tomcat implements
the Servlet specification, it customizes the implementation class of the HttpServletRequest interface. At the same time, the JavaEE specification also defines HttpServletRequestWrapper, which is the wrapper class of the request class and uses the decorator mode. Regardless of how various application server vendors implement the HttpServletRequest interface,
users who want to customize requests only need to inherit HttpServletRequestWrapper and override a certain method, and then pass
the request into the request wrapper class, and the decorator mode will replace the request object corresponding to a method. The user's code and the server
manufacturer's code are completely decoupled. We don't need to care about how the HttpServletRequest interface is implemented. With the help of the wrapper class, we
can modify the methods in the request at will.

The code contains most of the commonly used methods

package com.wx.config.xss;

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.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

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();
        Map<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)) {
    
    
                        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();
        StringBuffer body = new StringBuffer();
        InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8"));
        BufferedReader buffer = new BufferedReader(reader);
        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> resultMap = new HashMap(map.size());
        for (String key : map.keySet()) {
    
    
            Object val = map.get(key);
            if (map.get(key) instanceof String) {
    
    
                resultMap.put(key, HtmlUtil.filter(val.toString()));
            } else {
    
    
                resultMap.put(key, val);
            }
        }
        String str = JSONUtil.toJsonStr(resultMap);
        final ByteArrayInputStream bain = new ByteArrayInputStream(str.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 listener) {
    
    
            }
        };
    }
}

4. Create a filter and pass all request objects into the wrapper class

package com.wx.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 {
    
    
    public void init(FilterConfig config) throws ServletException {
    
    
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain
            chain)
            throws IOException, ServletException {
    
    
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
                (HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }

    @Override
    public void destroy() {
    
    
    }
}

Also don't forget
to add the annotation @ServletComponentScan to the springboot main class

After using the @ServletComponentScan annotation on SpringBootApplication,
the Servlet can be automatically registered directly through the @WebServlet annotation.
The Filter can be automatically registered directly through the @WebFilter annotation.
The Listener can be automatically registered directly through the @WebListener annotation.


The dividing line
is normal when testing the business. The Chinese scene in the later test was thunderous.
Stepped on the pit.
insert image description here
Chinese requests without the above code are also normal.
After adding the above code, the Chinese request is like this.
Post an error: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error. . . . . . . . . . . . . . . . . . . . . . .
I read a lot of posts talking about the character set problem, and then I went to check for a long time and finally found the
IDAE configuration in the picture: the global encoding GBK is changed to UTF-8.
insert image description here

Searched a lot of stickers. I didn't understand the difference between global encoding and project encoding in the IDEA settings here (and why this pit was triggered).
Welcome everyone to comment.

Guess you like

Origin blog.csdn.net/wuyang1115998756/article/details/128174673