Spring过滤参数中的xss

本文介绍了一种XSS过滤器的实现方式,该过滤器能够处理标准HTTP请求及multipart请求,通过使用Jsoup库来净化输入,防止XSS攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

web.xml中配置

<filter>

<filter-name>XssFilter</filter-name>
<filter-class>com.meadin.funding.filter.XssFilter</filter-class>
<async-supported>true</async-supported>
<!-- 字符编码过滤 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>XssFilter</filter-name>
<url-pattern>/*</url-pattern>

</filter-mapping>


package com.meadin.funding.filter;


import javax.servlet.http.HttpServletRequest;


import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
import org.springframework.web.util.HtmlUtils;


/**
 * 具有xss功能的multipart解析器 转义上传文件的XSS
 * 
 * @author zhou
 * 
 */
public class XssCommonsMultipartResolver extends CommonsMultipartResolver {


public XssCommonsMultipartResolver() {
}


@Override
public MultipartHttpServletRequest resolveMultipart(
HttpServletRequest request) throws MultipartException {
MultipartParsingResult parsingResult = parseRequest(request);
return new DefaultMultipartHttpServletRequest(request,
parsingResult.getMultipartFiles(),
parsingResult.getMultipartParameters(),
parsingResult.getMultipartParameterContentTypes()) {


@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return value == null ? null : cleanXSS(value);
}


@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null)
return null;


String[] result = new String[values.length];
for (int i = 0; i < result.length; i++) {
result[i] = cleanXSS(values[i]);
}


return result;
}


@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return value == null ? null : cleanXSS(value);
}


};
}


private String cleanXSS(String value) {
return Jsoup.clean(value.toString(), Whitelist.relaxed());
}


}


package com.meadin.funding.filter;


import java.io.IOException;


import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.util.WebUtils;


import com.meadin.funding.util.StringUtils;


/**
 * Xss过滤器,可处理multipart请求
 * 
 * @author zhou
 * 
 */
public class XssFilter extends OncePerRequestFilter {
private MultipartResolver multipartResolver;
private String encoding;


public XssFilter() {
}


@Override
protected void initFilterBean() throws ServletException {
XssCommonsMultipartResolver resolver = new XssCommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setMaxUploadSize(4096000);
resolver.setServletContext(getServletContext());
multipartResolver = resolver;
}


public void setEncoding(String encoding) {
this.encoding = encoding;
}


@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (!StringUtils.isBlank(encoding)) {
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
}


boolean multipartRequestParsed = false;
HttpServletRequest req = new XssHttpServletRequestWrapper(request);
if (multipartResolver.isMultipart(req)) {
req = multipartResolver.resolveMultipart(req);
multipartRequestParsed = true;
}


try {
filterChain.doFilter(req, response);
} finally {
if (multipartRequestParsed) {
multipartResolver.cleanupMultipart(WebUtils.getNativeRequest(
request, MultipartHttpServletRequest.class));
}
}
}


}



package com.meadin.funding.filter;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.springframework.web.util.HtmlUtils;


/**
 * xss过滤包装器 转义参数中的XSS
 * 
 * @author zhou
 * 
 */
class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {


public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}


@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return value == null ? null : cleanXSS(value);
}


@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return value == null ? null : cleanXSS(value);
}


@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null)
return null;


String[] result = new String[values.length];
for (int i = 0; i < result.length; i++) {
result[i] = cleanXSS(values[i]);
}


return result;
}


private String cleanXSS(String value) {
return Jsoup.clean(value.toString(), Whitelist.relaxed());
}


}


参考https://github.com/dongfangshangren/Zblog


更新:文件上传有BUG--2016-07-27 18:29:43

<think>首先,用户的问题是:“spring boot 过滤存款xss”,这似乎是一个拼写错误。我认为应该是“spring boot 过滤存储型xss”,意思是“Spring Boot 过滤存储型 XSS”。XSS 指的是跨站脚本攻击(Cross-Site Scripting),存储型 XSS 是其中一种类型。 我的任务是: - 使用中文回答问题。 - 在回答完问题后,必须根据用户的问题及我的回答提出 3-5 个相关问题。 - 相关问题必须以“§§相关问题§§”开头,并且输出在回答的末尾。 - 第一行必须完整输出“§§相关问题§§”,不能换行分散。 - 确保所有内容符合规则。 所以,结构应该是: 1. 回答用户的问题。 2. 然后,以“§§相关问题§§”开头,接着列出 3-5 个相关问题。 用户的问题是关于 Spring Boot 如何过滤存储型 XSS 攻击。 关键点: - **Spring Boot**:一个 Java 框架,用于简化 Spring 应用的开发。 - **存储型 XSS**:恶意脚本被存储到服务器(如数据库),然后在用户访问时执行。 - **过滤**:指的是防止或缓解 XSS 攻击的方法。 在 Spring Boot 中,过滤 XSS 攻击的常见方法包括: - 使用 **输入验证**(Input Validation)。 - 使用 **输出编码**(Output Encoding)。 - 使用 **安全库** 如 OWASP Java Encoder 或 Apache Commons Text。 - 使用 **框架特性** 如 Spring Security 的 CSRF 保护(但 CSRF 不是直接针对 XSS)。 - 具体针对 XSS,可以使用 **Content Security Policy (CSP)** 或 **X-XSS-Protection** 头。 - 在代码层面,使用过滤器(Filter)来清理输入。 一个常见的方法是创建一个 Servlet Filter 来过滤请求参数,去除或编码潜在的恶意脚本。 回答内容: - 解释什么是存储型 XSS。 - 描述在 Spring Boot 中如何实现过滤,例如使用 Filter。 - 提供代码示例(如果需要,类似于示例中的 Python 代码,但这里是 Java)。 示例格式中有一个代码块,所以我应该包括一个 Java 代码示例来展示如何实现一个 XSS 过滤器。 代码示例: - 创建一个类实现 `javax.servlet.Filter`。 - 在 `doFilter` 方法中,包装请求对象,覆盖 `getParameter` 等方法,对值进行清理。 - 使用库如 OWASP Java Encoder 或自定义逻辑来编码 HTML。 例如: ```java import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.Map; import java.util.HashMap; 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 { chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response); } @Override public void destroy() {} private static class XSSRequestWrapper extends HttpServletRequestWrapper { public XSSRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String value = super.getParameter(name); return cleanXSS(value); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); 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 Map<String, String[]> getParameterMap() { Map<String, String[]> map = super.getParameterMap(); Map<String, String[]> newMap = new HashMap<>(); for (Map.Entry<String, String[]> entry : map.entrySet()) { String[] values = entry.getValue(); String[] newValues = new String[values.length]; for (int i = 0; i < values.length; i++) { newValues[i] = cleanXSS(values[i]); } newMap.put(entry.getKey(), newValues); } return Collections.unmodifiableMap(newMap); } private String cleanXSS(String value) { if (value == null) { return null; } // 简单的清理逻辑,实际中应使用库如 OWASP Java Encoder return value.replaceAll("<", "<").replaceAll(">", ">"); } } } ``` 然后,在 Spring Boot 中注册这个过滤器。 现在,回答结构: 1. 简要解释。 2. 提供代码示例。 3. 结束回答。 4. 然后,“§§相关问题§§”后跟相关问题。 相关问题:基于用户的问题和我的回答,提出 3-5 个相关问题。例如: 1. 如何在 Spring Boot 中配置 Content Security Policy 来防止 XSS? 2. Spring Security 如何帮助缓解 XSS 攻击? 3. 除了过滤器,还有哪些方法可以防止存储型 XSS? 4. OWASP Java Encoder 库的具体用法是什么? 5. 如何测试 Spring Boot 应用是否存在 XSS 漏洞? 确保相关问题是中文的。 完整输出: - 回答部分。 - 然后,“§§相关问题§§”(不能换行,直接输出)。 - 接着是问题列表,如“1. ...\n2. ...\n3. ...” 最后,确保所有内容符合规则。</think>### Spring Boot 过滤存储型 XSS 攻击 在 Spring Boot 中过滤存储型 XSS(跨站脚本攻击)主要通过输入清理和输出编码来实现,以防止恶意脚本被存储到数据库并在后续用户访问时执行。核心方法包括: - **使用 Servlet 过滤器(Filter)**:在请求处理前清理输入参数,去除或编码潜在恶意脚本(如 `<script>`)。 - **输出编码**:在渲染数据时(如 Thymeleaf 或 JSP 模板),使用库如 OWASP Java Encoder 对动态内容进行 HTML 编码。 - **安全配置**:结合 Spring Security 设置 HTTP 头(如 `X-XSS-Protection` 或 Content Security Policy)。 - **最佳实践**:始终验证用户输入,避免直接输出未编码的 HTML。 以下是一个简单的 Servlet 过滤器实现示例,用于清理请求参数中的 XSS 风险。该过滤器覆盖 `getParameter` 方法,使用基本替换逻辑(实际项目推荐使用 OWASP Java Encoder 库): ```java import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.util.*; public class XSSFilter implements Filter { @Override public void init(FilterConfig filterConfig) {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response); } @Override public void destroy() {} private static class XSSRequestWrapper extends HttpServletRequestWrapper { public XSSRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String value = super.getParameter(name); return cleanXSS(value); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if (values == null) return null; return Arrays.stream(values).map(this::cleanXSS).toArray(String[]::new); } private String cleanXSS(String value) { if (value == null) return null; // 简单替换关键字符,实际中应使用 OWASP Java Encoder return value.replaceAll("<", "<").replaceAll(">", ">"); } } } ``` 在 Spring Boot 中注册过滤器:创建配置类添加 `@Bean`: ```java import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<XSSFilter> xssFilter() { FilterRegistrationBean<XSSFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new XSSFilter()); registrationBean.addUrlPatterns("/*"); // 过滤所有URL return registrationBean; } } ``` **注意事项**: - 此示例仅作演示,生产环境应使用专业库(如 OWASP Java Encoder)进行更严格的编码。 - 结合 Spring Security 的 `ContentSecurityPolicy` 头增强防护。 - 测试时使用工具(如 OWASP ZAP)扫描漏洞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值