Table of contents
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
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