Webman需在响应前显式调用脱敏函数或通过中间件拦截输出,否则敏感数据直接透出;推荐在全局中间件中对JSON响应递归脱敏mobile、phone等字段,校验输入后再掩码,覆盖HTTP接口、导出文件及日志等所有出口。

Webman 没有内置字段脱敏机制,不能靠配置自动触发;必须在响应前显式调用脱敏函数或借助事件/中间件拦截输出,否则原始敏感数据会直接透出。
Webman 响应层脱敏:在 response 发送前统一处理
Webman 的生命周期中,response 对象生成后、真正 send 之前是最后可控节点。推荐在全局中间件里对 Response 内容做 JSON 解析 + 字段替换,而不是改模型或控制器——这样能覆盖所有 HTTP 接口(包括未走模型的原生查询、路由闭包等)。
- 仅对
Content-Type: application/json响应生效,跳过 HTML、文件下载等非结构化响应 - 用
json_decode($content, true)解析响应体,避免正则误伤字符串内的 JSON 片段 - 递归遍历数组,匹配键名如
mobile、phone、id_card、identity等常见敏感字段别名 - 对匹配到的值调用统一脱敏函数(如
mask_phone()),不修改原始键名,只替换值 - 失败时(如 JSON 解析异常)原样返回,不中断请求
mask_phone() 和 mask_idcard() 必须校验输入再截取
直接 substr_replace($phone, '****', 3, 4) 是危险的——空值、短于11位、含中文括号或空格的手机号都会导致结果错位甚至报错。脱敏函数本身要自防御。
- 手机号先用
preg_replace('/\D/', '', $phone)清洗,再用strlen() === 11校验,不满足直接返回原值或空字符串 - 身份证需区分 15 位和 18 位:
strlen($id) === 18 ? substr_replace($id, '******', 6, 8) : (strlen($id) === 15 ? substr_replace($id, '******', 6, 6) : $id) - 18 位身份证末位可能是
X或x,用substr($id, -4)安全获取,不要用mb_substr截取(会把X当成双字节字符切坏) - 所有函数签名强制类型声明:
function mask_phone(string $phone): string,避免传入null导致strlen(null)返回 0 而不是报错
关联查询或数组嵌套结构下,别依赖模型访问器
Webman 不是 Laravel 或 ThinkPHP,没有 get*Attr 或 withAttr 这类模型钩子。即使你用了 ORM(如 Medoo 或 Eloquent),其访问器在 Webman 的纯 HTTP 流程中默认不触发,除非你手动调用 toArray() 并确保访问器已注册。
立即学习“PHP免费学习笔记(深入)”;
- 如果数据来自
Db::select()或原生 PDO 查询,返回的是纯数组,访问器完全无效 - 导出 CSV/Excel 时同样绕过模型,必须在
array_map阶段单独调用脱敏函数 - 对嵌套结构(如
['user' => ['profile' => ['mobile' => '13812345678']]]),中间件里的递归逻辑比模型层更可靠 - 不要在中间件里尝试反序列化对象——Webman 响应体是字符串,不是 PHP 对象流
导出文件和日志里也得脱敏,但方式完全不同
CSV 导出和错误日志是两个典型“逃逸点”:它们不经过 HTTP 响应中间件,也不会被 JSON 解析逻辑捕获。
- 导出前用
array_map显式清洗:array_map(fn($row) => ['mobile' => mask_phone($row['mobile']), 'id_card' => mask_idcard($row['id_card'])], $data) - 日志记录前检查字段名,对
$logContext['mobile']等敏感键主动脱敏,禁止直接Log::info('user login', $user) - Webman 的
Logger默认不格式化数组,print_r($user, true)会把完整手机号打进去,必须提前剥离或替换 - 环境变量或配置中若硬编码测试用手机号/身份证,启动时就要用
mask_phone($_ENV['TEST_PHONE'] ?? '')处理,防止调试时意外泄露
真正难的不是写对一个 substr_replace,而是让所有出口——HTTP 响应、导出文件、日志、CLI 输出、缓存序列化值——都走同一套校验+脱敏逻辑,且不互相干扰。Webman 的轻量特性意味着你得自己补全这个链路,而不是等框架帮你兜底。



















