SpringBoot 解决跨站脚本漏洞(XSS)问题

news/2024/11/16 16:54:06/

一、问题背景

使用 SpringBoot 的项目出现了跨站脚本漏洞(XSS)问题。


二、解决方案

步骤如下:

1、添加maven依赖

在 pom.xml 文件中,增加如下依赖:

		<dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-servlet-api</artifactId><version>8.0.36</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency>

2、新增 XSSFilter.java

config 目录下增加 XSSFilter.java,用于对请求接口进行过滤。
代码如下:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@WebFilter(filterName="XSSFilter", urlPatterns="/*")
public class XSSFilter implements Filter {FilterConfig filterConfig = null;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);}@Overridepublic void destroy() {this.filterConfig = null;}}

3、新增 XssHttpServletRequestWrapper.java

config 目录下,新增 XssHttpServletRequestWrapper.java,用于对请求参数进行预处理和解析。
代码如下:

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {public XssHttpServletRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String[] getParameterValues(String parameter) {String[] values = super.getParameterValues(parameter);if (values==null)  {return null;}int count = values.length;String[] encodedValues = new String[count];for (int i = 0; i < count; i++) {encodedValues[i] = cleanXSS(values[i]);}return encodedValues;}@Overridepublic String getParameter(String parameter) {String value = super.getParameter(parameter);if (value != null) {return cleanXSS(value);}return null;}/*** 对 application/x-www-form-urlencoded 格式的POST请求参数,进行 cleanXSS解析* @return cleanXSS解析后的参数*/@Overridepublic Map<String, String[]> getParameterMap() {Map<String, String[]> values = super.getParameterMap();if (values == null) {return null;}Map<String, String[]> result = new HashMap<>();for (String key : values.keySet()) {String encodedKey = cleanXSS(key);int count = values.get(key).length;String[] encodedValues = new String[count];for (int i = 0; i < count; i++) {encodedValues[i] = cleanXSS(values.get(key)[i]);}result.put(encodedKey, encodedValues);}return result;}@Overridepublic String getHeader(String name) {String value = super.getHeader(name);if (value == null)return null;return cleanXSS(value);}private static String cleanXSS(String value) {value = value.replaceAll("<", "<").replaceAll(">", ">");value = value.replaceAll("%3C", "<").replaceAll("%3E", ">");value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");value = value.replaceAll("%28", "(").replaceAll("%29", ")");value = value.replaceAll("'", "'");value = value.replaceAll("eval\\((.*)\\)", "");value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");value = value.replaceAll("script", "");return value;}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ());return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) { }};}public String inputHandlers(ServletInputStream servletInputStream){StringBuilder sb = new StringBuilder();BufferedReader reader = null;try {reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (servletInputStream != null) {try {servletInputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return  cleanXSS(sb.toString ());}}

4、添加注解 @ServletComponentScan

XXXApplication.java 的类名上方,用于扫描配置类。添加注解如下:

@ServletComponentScan("com.XXX.config")

示例如下:
在这里插入图片描述



http://www.ppmy.cn/news/560947.html

相关文章

路由器与猫的区别

调制解调器&#xff0c;俗称“猫”&#xff0c;电话线的信号是模拟信号&#xff0c;电脑的信号是数字信号&#xff0c;要通过电话线上网就要用到“猫”将模拟信号和数字信号相互转换&#xff0c;也就是调制、解调&#xff0c;才能上网&#xff1b;路由器简单的说就是实现多机同…

光猫+路由器

光猫&#xff1a; 路由器&#xff1a; 路由器是将光猫输出的网络线进行多发给家庭使用。

路由器怎么连接猫

首先用一根网线与路由器和猫的wan口连接&#xff0c;接着用另一根网线与路由器的lan口和电脑设备&#xff0c;连好后在浏览器内输入网址&#xff1a;192.168.1.1&#xff0c;然后输入路由器的密码&#xff0c;登录成功后&#xff0c;再设置下无线路由器的密码&#xff0c;再将路…

光猫、路由器、Wifi的解释

一般家庭的网络环境都是这样的&#xff1a; 首先是一根入户光纤插到猫上面&#xff0c;然后再用网线连接了猫和路由器。然后再用网线连接路由器和电脑。也可以通过路由器发射的wifi连接到路由器上面。 "猫"(Modem&#xff0c;调制解调器)&#xff0c;因为它的英文名…

动态ip与静态ip的概念、区别、应用场景

动态ip与静态ip的区别 前言一、介绍IP地址的概念和作用1.1、IP地址的定义1.2、IP地址的作用 二、动态IP和静态IP的区别2.1、动态IP和静态IP的定义2.2、动态IP和静态IP的特点2.3、动态IP和静态IP的优缺点比较 三、动态IP和静态IP的应用场景3.1. 动态IP的应用场景3.2. 静态IP的应…

Linux系统编程(vfork和fork)

文章目录 前言一、vfork讲解二、vfork使用三、exit和_exit1.exit和_exit对比2.在vfork中的使用 四、vfork和fork区别总结 前言 本篇文章讲解vfork和fork创建进程的区别。 一、vfork讲解 vfork 是一个在类Unix操作系统中的系统调用&#xff0c;它创建一个新进程&#xff0c;且…

类纸膜可以使用多久

类纸膜可以使用多久 在淘宝上买的几十元左右的ipad类纸膜&#xff0c;平时经常上课做笔记&#xff0c;还有打游戏&#xff0c;刚开始阻尼感很强&#xff0c;写字很舒服&#xff0c;就是打游戏不太滑比较影响游戏体验。 大概用了半年多不到一年&#xff0c;用pencil笔再写字时…

3M

很遗憾&#xff0c;以前都没听过这个&#xff2e;&#xff22;的公司&#xff0c;不过我这个市井小民肯定也不应该会知道这个号称为“道琼斯指数常青树的&#xff13;&#xff2d;”。其实&#xff0c;我们可能每天都有跟这个公司生产的产品打交道&#xff0c;最为人熟知的要数…