
SpringBoot集成Hutool防止XSS攻击实现
xss是跨站攻击脚本的简写。xss的攻击方式是发生在用户使用浏览器时候运行,通过嵌入脚本窃取用户信息(如cookie等)。相比钓鱼网站更难被发现,一般是用JavaScript实现。//拦截请求@Override}@Override//先进行转义在把请求返回}@Override}}
·
目录
思路如下: 一 定义过滤器 XssFillter继承Fillter拦截http请求
二 使用工具类继承 HttpServletRequestWrapper 进行请求转义
定义
xss是跨站攻击脚本的简写。xss的攻击方式是发生在用户使用浏览器时候运行,通过嵌入脚本窃取用户信息(如cookie等)。相比钓鱼网站更难被发现,一般是用JavaScript实现。
解决方法
一 前端设置,如使用vue 可以设置 httponly
二 后端http请求进行转义操作(这里主要介绍这一种)
思路如下:
一 定义过滤器 XssFillter继承Fillter拦截http请求
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() {
}
}
二 使用工具类继承 HttpServletRequestWrapper 进行请求转义
HttpServletRquestWrapper继承体系如下图,工具类继承HttpServletRequestWrapper,并复写getParameterNames、getParameter、getParameterValues等方法即可简单进行http请求转义
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) {
}
};
}
}
三 配置启动类
启动类应启用servlet扫描
四 控制层
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());
}
}
测试
在swagger2测试截图如下
更多推荐
所有评论(0)
您需要登录才能发言
查看更多评论