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


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; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse); } @Override public 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); } @Override public 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; } @Override public 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解析后的参数 */ @Override public 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; } @Override public 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("<", "&lt;").replaceAll(">", "&gt;"); value = value.replaceAll("%3C", "&lt;").replaceAll("%3E", "&gt;"); value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;"); value = value.replaceAll("%28", "&#40;").replaceAll("%29", "&#41;"); value = value.replaceAll("'", "&#39;"); value = value.replaceAll("eval\\((.*)\\)", ""); value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); value = value.replaceAll("script", ""); return value; } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ()); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public 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")

 

示例如下:

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM