java过滤跨站脚本攻击_SpringBoot过滤XSS脚本攻击

SpringBoot防止XSS攻击:过滤与序列化解决方案
本文介绍了如何在SpringBoot项目中防止XSS攻击,提供了通过后台转译方式处理XSS的解决方案,包括重写`getParameter`和`getParameterValues`方法进行querystring类型参数过滤,并通过自定义`JsonSerializer`过滤json类型参数。

前排提醒

源码在最后

XSS攻击是什么

XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web客户将代码植入到提供给其它客户使用的页面中。

简而言之,就是作恶客户通过表单提交少量前台代码,假如不做解决的话,这些前台代码将会在展现的时候被浏览器执行。

如何避免XSS攻击

这里我根据个人经验做一个总结,可能经验也有不足之处。我个人处理XSS攻击是通过后台转译的办法来处理的。在实际项目中,react、vue等前后台完全分离的框架似乎已经帮我们解决了XSS脚本,这个本人对于前台略懂皮毛而已,这里就不做讨论了。下面主要实现以后台做XSS过滤。

代码实现

对于过滤XSS脚本的代码,通过搜索引擎可以搜索到很多,但似乎都不是那么全面。基本上都是只能过滤querystring类型的入参,而不能过滤json类型的入参。其实,在现在的开发中,更多的是使用json类型做数据交互。下面就直接贴代码了:

XssAndSqlHttpServletRequestWrapper.javapackage com.loger.filter;

import org.apache.commons.lang3.StringUtils;

import org.apache.commons.text.StringEscapeUtils;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

/**

* @author Loger

* 防止XSS攻击

*/

public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

private HttpServletRequest request;

public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {

super(request);

this.request = request;

}

@Override

public String getParameter(String name) {

String value = request.getParameter(name);

if (!StringUtils.isEmpty(value)) {

value = StringEscapeUtils.escapeHtml4(value);

}

return value;

}

@Override

public String[] getParameterValues(String name) {

String[] parameterValues = super.getParameterValues(name);

if (parameterValues == null) {

return null;

}

for (int i = 0; i < parameterValues.length; i++) {

String value = parameterValues[i];

parameterValues[i] = StringEscapeUtils.escapeHtml4(value);

}

return parameterValues;

}

}

简单讲解下,这里重写了两个方法:getParameter和getParameterValues,getParameter方法是直接通过request取得querystring类型的入参调用的方法。假如是通过springMVC注解类型来取得参数的话,走的是getParameterValues的方法。

StringEscapeUtils.escapeHtml4这个方法来自Apache的工具类,maven坐标如下:org.apache.commons

commons-text

1.4

过滤的代码写完了,下面就是在一个filter中应用该代码。

XssFilter.javapackage com.loger.filter;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.module.SimpleModule;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Primary;

import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

/**

* @author Loger

*/

@WebFilter

@Component

public class XssFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req);

chain.doFilter(xssRequestWrapper, response);

}

@Override

public void destroy() {

}

/**

* 过滤json类型的

* @param builder

* @return

*/

@Bean

@Primary

public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {

//解析器

ObjectMapper objectMapper = builder.createXmlMapper(false).build();

//注册xss解析器

SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer");

xssModule.addSerializer(new XssStringJsonSerializer());

objectMapper.registerModule(xssModule);

//返回

return objectMapper;

}

}

就这样,过滤querystring类型的代码已经完成(xssObjectMapper这个是后面过滤json类型才用到的)。下面来实现过滤json类型的代码:

XssStringJsonSerializer.javapackage com.loger.filter;

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.JsonSerializer;

import com.fasterxml.jackson.databind.SerializerProvider;

import org.apache.commons.text.StringEscapeUtils;

import java.io.IOException;

public class XssStringJsonSerializer extends JsonSerializer{

@Override

public ClasshandledType() {

return String.class;

}

@Override

public void serialize(String value, JsonGenerator jsonGenerator,

SerializerProvider serializerProvider) throws IOException {

if (value != null) {

String encodedValue = StringEscapeUtils.escapeHtml4(value);

jsonGenerator.writeString(encodedValue);

}

}

}

这里通过修改SpringMVC的json序列化来达到过滤xss的目的的。其实也可以通过第一种方法,重写getInputStream方法来实现,但因为得到的是ServletInputStream,不太好解决。(通过json类型传参会走getInputStream方法,通过重写该方法打印输出可以证实)

下面可以通过几个例子验证下能否成功:

简单写一个controller

TestController.javapackage com.loger.controller;

import org.springframework.web.bind.annotation.*;

import org.springframework.web.multipart.MultipartFile;

/**

* @author Loger

* Date: 2018-10-05

* TIme: 19:14

* Description :

*/

@RestController

@RequestMapping(value = "/test")

public class TestController {

@PostMapping(value = "/xss")

public Object test(String name) {

System.out.println(name);

return name;

}

@PostMapping(value = "/json")

public Object testJSON(@RequestBody Param param) {

return param;

}

@GetMapping(value = "/query")

public Object testQuery(String q){

return q;

}

@PostMapping(value = "/upload")

public Object upload(MultipartFile file){

System.out.println(file.getOriginalFilename());

return "OK";

}

}

下面通过postman测试下效果:

0f47066d8dc3101dee964b2f20c26084.png

d4ce0f94424e35ec93cdd94f466a16fb.png

0233ab8b8109d98da0f8c52e53a62701.png

git地址:https://github.com/logerchen/springboot-xss.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值