初级脚手架中用字符过滤流实现敏感词动态清洗,核心是将过滤逻辑嵌入数据读取过程,通过自定义reader封装trie树匹配与替换,启动时加载词库、支持热更新,并采用最长前缀匹配和utf-8安全替换。

在初级脚手架中用字符过滤流实现敏感词动态清洗,核心是把过滤逻辑“嵌入到数据读取过程中”,而不是等整段文本加载完再处理。这种方式内存占用低、响应及时,特别适合表单提交、日志解析、文件导入等场景。
用自定义 Reader/InputStream 封装清洗逻辑
不依赖中间字符串拼接,而是对原始输入流做一层包装:
- Java 中可继承 FilterReader 或实现 Reader 接口,在
read(char[] cbuf, int off, int len)方法里逐块解码、匹配、替换 - 每读入一批字符(如 1024 字符),就用 Trie 树做滑动匹配;命中敏感词立即替换成
***,并跳过对应长度,避免重复扫描 - 内部维护当前匹配状态(如 Trie 节点指针、已读字符缓冲区),确保中文、emoji、混合编码不中断匹配
词库加载与结构准备要轻量可靠
避免每次读取都查文件或数据库:
- 把敏感词按行存为
resources/sensitive-words.txt,启动时一次性构建内存 Trie 树 - Trie 节点只需记录
isEnd、wordLength和可选的替换标记,50 行 Java 即可完成 - 若需热更新,后续加个
FileWatcher监听文件变化 + 原子替换 root 节点即可,不影响正在运行的流
边界处理与安全替换不能省略
防止误伤和信息泄露:
- 采用“最长前缀匹配”:当 “色情” 和 “色情内容” 同时存在,优先匹配更长的词,避免只替换了前半截
- 严格按字符(rune / char)推进,不用
substring,天然兼容 UTF-8 中文、日文、Emoji - 替换统一用固定长度星号(如
***),不按原词长度生成,防止攻击者通过输出长度反推敏感词
集成进脚手架要最小侵入
以 Spring Boot 为例,无需改业务代码:
- 定义一个 @Component 工具类,提供
clean(InputStream in)或clean(Reader reader)方法 - 在 Controller 层接收参数后,直接传入:
filterService.clean(request.getReader()) - 如需全局生效,可用 RequestBodyAdvice 拦截所有
@RequestBody,对 JSON 字段中的字符串值递归清洗(配合反射遍历)











