在开始构建公告内容防护系统之前,我们需要准备一个基础的 Spring Boot 项目环境。本指南将基于 Java 语言和 Spring Boot 框架进行演示,核心防护逻辑不依赖特定框架,可轻松移植到其他语言环境。
在项目的 pom.xml 文件中引入 Jsoup 依赖。Jsoup 是一款 Java 的 HTML 解析器,我们将利用其强大的 Whitelist(白名单)机制来过滤 XSS 攻击。
```xml确保项目能够正常加载 Maven 依赖后,我们进入核心代码的编写阶段。整个防护体系分为两个部分:XSS 过滤(防止脚本注入)和敏感词过滤(防止违规内容发布)。
公告系统通常允许富文本输入,以便支持排版,但这同时也给了攻击者注入 Script 标签或事件属性的机会。我们不能直接禁用所有 HTML 标签,而是需要定义一个严格的白名单,仅保留安全的标签(如 p, br, span, b)和属性。
创建一个名为 XssCleanUtil 的工具类。这个类将封装 Jsoup 的清理逻辑,并提供静态方法供业务层直接调用。
```java import org.jsoup.Jsoup; import org.jsoup.safety.Safelist; public class XssCleanUtil { / 配置安全的 HTML 白名单 仅允许基本的文本格式标签,拒绝 script, iframe, object 等危险标签 / private static final Safelist WHITELIST = Safelist.relaxed() .addTags("h1", "h2", "h3", "h4", "h5", "h6") // 允许标题 .addTags("p", "span", "div", "br") // 允许段落和换行 .addTags("ul", "ol", "li") // 允许列表 .addTags("b", "strong", "i", "em", "u") // 允许文字样式 .addAttributes("span", "style") // 允许 span 拥有 style 属性(注意:此处需配合 CSS 过滤,暂仅演示基础) .addProtocols("a", "href", "http", "https") // 仅允许 http/https 链接 .removeProtocols("a", "href", "ftp", "javascript"); // 移除危险协议 / 清理输入的 HTML 字符串 @param dirtyHtml 用户输入的原始 HTML @return 清理后的安全 HTML / public static String clean(String dirtyHtml) { if (dirtyHtml == null || dirtyHtml.trim().isEmpty()) { return ""; } // 使用 Jsoup 进行清理,OutputSettings().prettyPrint(false) 避免改变原有换行结构 return Jsoup.clean(dirtyHtml, WHITELIST) .outputSettings(new org.jsoup.nodes.Document.OutputSettings().prettyPrint(false)); } } ```在上述代码中,我们使用了 Safelist.relaxed() 作为基础,它允许大部分常用的文本标签。随后我们通过 addTags 显式增加了标题和列表标签,确保公告内容具备基本的可读性。
关键操作点:必须调用 removeProtocols 移除 javascript: 协议。否则,攻击者可能构造 点击 绕过标签检测。同时,我们禁用了 img 标签的 onerror 事件(Jsoup 默认会移除所有事件处理器),这是防止 XSS 触发的重要一环。
除了脚本攻击,公告内容还需要过滤政治、色情或广告等敏感词。正则表达式在处理大量敏感词时性能较差,这里我们采用 DFA(确定性有限自动机)算法,将敏感词库预处理成一个 Map 结构,实现 O(n) 时间复杂度的快速匹配。
在项目的 src/main/resources 目录下创建一个名为 sensitive-words.txt 的文件。每行一个敏感词,编码格式务必保存为 UTF-8。
坏蛋 赌博 私服 中奖
创建 SensitiveWordFilter 类。在类加载时(静态代码块)读取文件并构建 DFA 模型。
```java import java.io.; import java.util.; public class SensitiveWordFilter { // 敏感词匹配树 private static Map在同一个类中添加检测方法。该方法遍历输入文本的每一个字符,在 DFA 树中查找路径。如果发现 isEnd 标记为 true,则说明命中敏感词。
```java / 判断文本是否包含敏感词 @param text 待检测文本 @return true 包含,false 不包含 / public static boolean contains(String text) { if (text == null || text.trim().isEmpty()) { return false; } for (int i = 0; i < text.length(); i++) { int matchFlag = checkSensitiveWord(text, i); if (matchFlag > 0) { return true; // 发现敏感词,直接返回 } } return false; } / 从指定位置开始检查 @param text 全文 @param beginIndex 开始索引 @return 匹配到的敏感词长度,0表示未匹配 / private static int checkSensitiveWord(String text, int beginIndex) { boolean flag = false; int matchLength = 0; Map现在我们将 XSS 过滤和敏感词过滤集成到业务逻辑中。我们需要先进行 XSS 清理(净化 HTML),再进行敏感词检测(拦截违规语义)。
创建一个 NoticeController,模拟接收前端提交的公告内容。
```java import org.springframework.web.bind.annotation.; @RestController @RequestMapping("/api/notice") public class NoticeController { @PostMapping("/publish") public String publishNotice(@RequestBody NoticeDto noticeDto) { String rawContent = noticeDto.getContent(); // 步骤1:XSS 过滤 // 将危险的 HTML 标签和属性剥离,保留安全的富文本格式 String safeContent = XssCleanUtil.clean(rawContent); // 步骤2:敏感词检测 // 对过滤后的文本进行语义检测 if (SensitiveWordFilter.contains(safeContent)) { return "发布失败:内容包含违规敏感词,请检查后重试。"; } // 步骤3:业务逻辑处理(如保存数据库) // saveToDatabase(noticeDto.getTitle(), safeContent); return "发布成功!安全内容已入库。"; } // 简单的 DTO 类 static class NoticeDto { private String title; private String content; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } } ```启动 Spring Boot 项目,使用 Postman 或 curl 发送 POST 请求进行测试。
测试用例 1:XSS 攻击拦截
请求 Body(JSON):
{
"title": "系统升级通知",
"content": "系统将于今晚维护,请知悉。
"
}
预期结果:接口返回“发布成功”。查看数据库或日志,会发现内容已被清洗为:
系统将于今晚维护,请知悉。
script 标签已被完全移除,且保留了 p 标签。
测试用例 2:敏感词拦截
请求 Body(JSON):
{
"title": "活动推广",
"content": "点击链接参与赌博活动,大奖等你拿。
"
}
预期结果:接口返回“发布失败:内容包含违规敏感词,请检查后重试。”。因为“赌博”一词在 sensitive-words.txt 中已定义,DFA 算法成功匹配并拦截。
测试用例 3:组合攻击绕过尝试
攻击者可能尝试将敏感词拆分或利用 HTML 实体编码绕过。例如:
{
"title": "测试",
"content": "中
奖"
}
预期结果:Jsoup 的 clean 方法会移除带有 onerror 的 img 标签,将其变为纯文本或直接删除。如果最终剩余文本包含“中奖”且词库中有该词,同样会被拦截。这展示了多层防护的必要性。
易频IT社区是综合性互联网IT技术门户网站,专注分享网络技术、服务器运维、网络安全、编程开发、系统架构、云计算、大数据等行业干货,实时更新IT行业资讯、零基础教程、实战案例,为IT从业者、技术爱好者提供专业的学习交流平台。
Copyright © 2021-2026 易频IT社区. All Rights Reserved. 备案号:闽ICP备2023013482号 网站地图