Apache中用mod_substitute动态替换敏感词需启用substitute和filter模块,绑定MIME类型,用s#...#...#gn语法写正则规则,通过LocationMatch精确控制路径,并优先结构锚定而非直接匹配中文。

要在 Apache 中用 mod_substitute 动态替换响应内容里的敏感词,核心是:启用模块、声明 MIME 类型、写对正则规则、避开编码和跨行陷阱。它不是“开了就能用”的功能,而是依赖配置链的精细操作。
必须先加载并串联两个模块
mod_substitute 本身不独立工作,必须与 mod_filter 配合。Apache 2.4+ 通常已编译这两个模块,但默认未启用:
- 执行
a2enmod substitute filter(Debian/Ubuntu)或手动在httpd.conf加两行:LoadModule substitute_module modules/mod_substitute.soLoadModule filter_module modules/mod_filter.so - 仅启用模块还不够——必须显式把响应体“挂”到 SUBSTITUTE 过滤链上。例如只处理 HTML 页面:
AddOutputFilterByType SUBSTITUTE text/html - 若需处理 JSON 接口返回的敏感字段(如身份证、手机号),还得加上:
AddOutputFilterByType SUBSTITUTE application/json
注意:Apache 不识别application/json; charset=utf-8这类带参数的类型,只认application/json主类型。
写敏感词替换规则的关键细节
敏感词替换看似简单,实际容易因符号、编码、上下文出错。正确写法要兼顾安全性和可维护性:
Apache 2.4.62 官方 tar.gz 源码包是 Linux 及类 Unix 系统构建 Web 服务器的核心基础。通过源码编译安装,开发者能够灵活定制模块、优化性能并精准控制安装路径,满足多样化的业务需求。
- 用
s///语法,推荐以#或|作分隔符,避免正则中斜杠冲突。比如替换手机号:Substitute "s#\"phone\":\"[0-9]{11}\"#\"phone\":\"****1234\"#g" - 双引号、反斜杠等 JSON 特殊字符必须转义;
\d在 Apache 正则中不支持,改用[0-9] - 加
g全局匹配、i忽略大小写(如 “Password” 和 “password” 都要脱敏) - 避免跨行误伤:如果后端返回美化格式(含换行缩进)的 JSON,建议关闭 gzip 并加
n标志(单行模式):SetEnv no-gzip 1Substitute "s#\"idCard\":\"[0-9]{17}[0-9X]\"#\"idCard\":\"*************X\"#gn"
路径控制与作用范围要精确
别让脱敏影响整个站点——只对特定业务接口生效才安全:
- 用
<LocationMatch>而非<Location>,防止路径误匹配。例如只处理用户详情接口:<LocationMatch "^/api/v1/user/detail$">
AddOutputFilterByType SUBSTITUTE application/json
Substitute "s#\"idCard\":\"[0-9]{17}[0-9X]\"#\"idCard\":\"*************X\"#gn"</LocationMatch> - 如果同时要处理 HTML 页面中的敏感词(如评论区昵称),可在对应 Location 块中加 HTML 类型过滤和规则,但注意规则顺序:先通用替换,再做敏感字段锚定,避免二次污染。
中文敏感词要特别谨慎
直接在正则里写中文(如 s/张三/***/g)极易导致乱码甚至页面解析失败,因为 mod_substitute 按字节流处理,不感知 UTF-8 编码边界:
- 首选方案:不匹配中文文本本身,改用结构锚定。例如替换“用户昵称”字段值,优先找
"nickname":"xxx"这样的 JSON 键值对模式 - 次选方案:确保后端响应头明确声明
Content-Type: text/html; charset=utf-8,且所有替换规则只操作 ASCII 字符(URL、ID、class 名等) - 实在绕不开中文关键词?考虑换用
mod_ext_filter调外部脚本(如 Python + re.sub),比硬扛 Apache 正则更可控

















