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.
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.
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.