手写SpringBoot项目XSS攻击过滤器实现
一、先来个简介
什么是XSS?
百度百科的解释: XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。
它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。
二、XSS分类
xss攻击可以分成两种类型:
1.非持久型攻击
2.持久型攻击
非持久型xss攻击:顾名思义,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响。非持久型xss攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。
持久型xss攻击:持久型xss,会把攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据一直存在。
也可以分成三类:
反射型:经过后端,不经过数据库
存储型:经过后端,经过数据库
三、废话不多说直接上代码
先加pom文件加上依赖
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.4</version> </dependency>
1.首先是要写个过滤器的包装类,这也是实现XSS攻击过滤的核心代码。
package com.hrt.zxxc.fxspg.xss; import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; 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.Map; /** * @program: fxspg * @description: XSS过滤具体核心代码 * @author: liumingyu * @date: 2020-01-10 14:28 **/ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { /** * @return * @Author liumingyu * @Description //TODO 构造函数,传入参数,执行超类 * @Date 2020/1/10 2:29 下午 * @Param [request] **/ public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) { super(request); } /** * @return java.lang.String * @Author liumingyu * @Description //TODO 重写getParameter方法 ,getParameter方法是直接通过request获得querystring类型的入参调用的方法 * @Date 2020/1/10 2:31 下午 * @Param [name] **/ @Override public String getParameter(String name) { String value = super.getParameter(name); if (!StringUtils.isEmpty(value)) { //调用Apache的工具类:StringEscapeUtils.escapeHtml4 value = StringEscapeUtils.escapeHtml4(value); } return value; } /** * @return java.lang.String[] * @Author liumingyu * @Description //TODO 重写getParameterValues * @Date 2020/1/10 2:32 下午 * @Param [name] **/ @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]; //调用Apache的工具类:StringEscapeUtils.escapeHtml4 parameterValues[i] = StringEscapeUtils.escapeHtml4(value); } return parameterValues; } @Override public String getHeader(String name) { return StringEscapeUtils.escapeHtml4(super.getHeader(name)); } @Override public String getQueryString() { return StringEscapeUtils.escapeHtml4(super.getQueryString()); } /** * @return javax.servlet.ServletInputStream * @Author liumingyu * @Description //TODO 过滤JSON数据中的XSS攻击 * @Date 2020/1/10 4:58 下午 * @Param [] **/ @Override public ServletInputStream getInputStream() throws IOException { //调用方法将流数据return为String String str = getRequestBody(super.getInputStream()); //如果str为"",则返回0 if ("".equals(str)) { return new ServletInputStream() { @Override public int read() throws IOException { return 0; } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } //将数据存放至map Map<String, Object> map = JSON.parseObject(str, Map.class); //声明个存放过滤后数据的hashMap Map<String, Object> resultMap = new HashMap<>(map.size()); //开始遍历数据 for (String key : map.keySet()) { Object val = map.get(key); //如果key=富文本字段名,就不去过滤 if ("content".equals(key)) { //不过滤 resultMap.put(key, val); } else { //不为富文本字段才会过滤 if (map.get(key) instanceof String) { //通过escapeHtml4去过滤 resultMap.put(key, StringEscapeUtils.escapeHtml4(val.toString())); } else { //不过滤 resultMap.put(key, val); } } } str = JSON.toJSONString(resultMap); final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(str.getBytes()); return new ServletInputStream() { @Override public int read() throws IOException { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } /** * @return java.lang.String * @Author liumingyu * @Description //TODO 获取JSON数据 * @Date 2020/1/10 4:58 下午 * @Param [stream] **/ private String getRequestBody(InputStream stream) { String line = ""; StringBuilder body = new StringBuilder(); int counter = 0; // 读取POST提交的数据内容 BufferedReader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8"))); try { while ((line = reader.readLine()) != null) { //拼接读取到的数据 body.append(line); counter++; } } catch (IOException e) { e.printStackTrace(); } if (body == null) { return ""; } //最后返回数据 return body.toString(); } }
2.看到这里你就已经完成了一半了加油!接下来的事情很简单写个过滤器就over 。
package com.hrt.zxxc.fxspg.xss; 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; /** * @program: fxspg * @description: XSS过滤器 * @author: liumingyu * @date: 2020-01-10 14:36 **/ @WebFilter @Component public class XssFilter implements Filter { /** * @return void * @Author liumingyu * @Description //TODO 重写init * @Date 2020/1/10 2:38 下午 * @Param [filterConfig] **/ @Override public void init(FilterConfig filterConfig) throws ServletException { } /** * @return void * @Author liumingyu * @Description //TODO 重写doFilter,将请求进行xss过滤 * @Date 2020/1/10 2:41 下午 * @Param [servletRequest, servletResponse, filterChain] **/ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //获取请求数据 HttpServletRequest req = (HttpServletRequest) servletRequest; //获取请求的url路径 String path = ((HttpServletRequest) servletRequest).getServletPath(); //声明要被忽略请求的数组 String[] exclusionsUrls = {".js", ".gif", ".jpg", ".png", ".css", ".ico"}; //遍历忽略的请求数组,若该接口url为忽略的就调用原本的过滤器,不走xss过滤 for (String str : exclusionsUrls) { if (path.contains(str)) { filterChain.doFilter(servletRequest, servletResponse); return; } } //将请求放入XSS请求包装器中,返回过滤后的值 XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req); filterChain.doFilter(xssRequestWrapper, servletResponse); } @Override public void destroy() { } }
注:上面的注释我都写得比较全了,不过多解释,so easy是不是!
相关推荐
sswqycbailong 2020-07-28
csxiaoqiang 2020-07-26
码农成长记 2020-07-19
layloge 2020-07-05
layloge 2020-06-26
liangjielaoshi 2020-06-25
csxiaoqiang 2020-06-16
某先生 2020-06-13
ItBJLan 2020-06-11
layloge 2020-06-07
csxiaoqiang 2020-06-03
sswqycbailong 2020-06-01
layloge 2020-05-30
码农成长记 2020-05-28
qidu 2020-05-26
zhuangnet 2020-05-20
zhuangnet 2020-05-19
xiaoemo0 2020-05-16
码农成长记 2020-05-10