☰
接口日志怎么脱敏:请求、响应和parameters数组不能只查一处
2026/10/3 7:15:38 网站建设 项目流程

目录

    • 一、日志能查错,也可能把不该保存的内容留下来
    • 二、先确认日志到底保存哪些东西
    • 三、用假响应检查请求与响应是否对称
    • 四、参数数组不能靠字段名自动识别
    • 五、响应也要经过结构化处理
    • 六、解析失败时,不宜默认原样保存
    • 七、先脱敏,再截断
    • 八、业务隐私和凭据采用不同规则
    • 九、验收脱敏要检查最终保存值

一、日志能查错,也可能把不该保存的内容留下来

接口对接需要请求、响应和任务记录,才能定位某张单失败在哪里。但日志脱敏不能只对请求对象里的password做一次替换。

我检查自己的日志模块时,发现它对请求调用了mask,对响应却直接序列化保存。这意味着“请求已经脱敏”不能证明整条日志都完成脱敏。

本文是本地代码审阅与构造样本复现。样本使用DEMO_ONLY等假值,没有读取账号文件,没有访问真实授权响应,也不能据此认定实际已经泄露凭据。文章由AI辅助整理,现有行为通过本地执行核对。

二、先确认日志到底保存哪些东西

项目日志记录包含连接标识、任务ID、动作、URL、请求、响应、HTTP状态、错误类别、耗时和时间。

这些字段服务于排错,但每个入口都需要自己的处理规则:

位置需要关注的内容
请求对象命名密钥字段、嵌套对象
参数数组按位置传递的签名或密码
响应对象token、临时凭据、业务敏感数据
URL查询参数中的敏感值
非JSON文本错误页、文本错误信息
导出文件导出前是否再次按用途过滤

通用递归函数主要解决命名字段。参数位置和响应结构,需要结合具体接口处理。

三、用假响应检查请求与响应是否对称

本地把日志模块的数据库写入替换为内存捕获,再给它一组假数据:

const{create}=require('./src/apilog');letsaved;constdb={prepare(){return{run(row){saved=row;}};}};constlog=create(db);log.record({connId:'test',action:'synthetic',url:'/example',request:{access_token:'DEMO_ONLY'},response:{access_token:'DEMO_ONLY'}});console.log(saved.request);console.log(saved.response);

这段复现没有创建数据库,也没有发网络请求。使用相对require路径时,示例应放在该项目根目录下执行。

当前模块保存的结果分别是:

{"access_token":"***"}
{"access_token":"DEMO_ONLY"}

请求里的假token被遮住,响应里的假token仍保留。这是通用记录函数的行为,不是某个真实接口已经返回token的证据。

四、参数数组不能靠字段名自动识别

通用mask会遍历对象和数组,但是它依据对象字段名判断敏感内容。看到下面的对象时,它不知道第一个字符串表示什么:

{"parameters":["DEMO_SIGNATURE_ONLY"]}

项目的金蝶客户端对此有单独处理:根据服务配置中的maskParams,把指定位置替换成星号,然后传给日志模块。

因此,不能仅凭通用mask无法识别位置参数,就推断当前签名登录链路没有遮蔽签名。应继续检查调用端是否预处理,以及服务配置的索引是否正确。

建议把位置规则绑定到具体接口动作,并针对该动作验证。不能给所有parameters数组使用同一套索引,因为各接口参数含义可能不同。

五、响应也要经过结构化处理

一个可行的改进方向,是让请求和响应走统一的日志净化入口,但使用各自适用的规则。

下面只展示“可解析JSON中的命名字段替换”,不是完整脱敏方案:

constsensitiveKeys=newSet(['password','pwd','appsecret','app_secret','access_token','refresh_token','token','authorization','cookie','set-cookie']);functionredactObject(value){if(Array.isArray(value))returnvalue.map(redactObject);if(value&&typeofvalue==='object'){returnObject.fromEntries(Object.entries(value).map(([key,item])=>[key,sensitiveKeys.has(key.toLowerCase())?'***':redactObject(item)]));}returnvalue;}

如果响应是JSON字符串,先解析,再递归处理,最后序列化。仅把字符串作为普通值递归遍历,不会识别字符串内部的字段。

敏感字段清单要按实际协议补充。上面的示例不会自动识别所有命名变体,也不会发现普通字符串中夹带的凭据。

六、解析失败时,不宜默认原样保存

项目当前mask遇到不是JSON的字符串,会原样返回。这有利于保留错误信息,但不能保证文本不含敏感值。

建议对无法解析的内容采用明确策略:只保留状态、内容类型、长度及受控的诊断信息,或者使用针对该接口设计的文本过滤规则。需要原文进一步排查时,应放在受权限控制的诊断流程里。

URL也要单独处理。对请求体脱敏,不会顺便清除URL查询参数中的值。复制报文到工单或截图时,同样要检查地址、响应和异常文本。

七、先脱敏,再截断

超长报文需要限制大小,但截断不会替代脱敏。

如果先截断JSON,再尝试解析,报文可能已经不完整,解析失败后进入原文兜底,就失去结构化处理机会。较稳妥的顺序是:解析、净化、序列化、限制长度。

项目里长度限制的常量叫MAX_BYTES,实际使用的是字符串length和slice。它限制的是JavaScript字符串的UTF-16代码单元数量,不是UTF-8字节数。需要按磁盘或传输字节预算控制时,应明确按字节计算,并避免在多字节字符中间切断。

八、业务隐私和凭据采用不同规则

密钥一般不需要靠明文排错;客户名称、联系方式、金额和商品明细则可能对排查有用,但需要按用途和权限控制。

内部排错记录和对外分享截图应采用不同视图。分享时保留字段结构、错误阶段和必要状态,隐藏可识别客户的信息;不要认为token已经遮住,整张订单就可以直接公开。

日志保留时间也要明确。项目有按时间删除日志行的实现,但这不自动等于备份、导出文件及SQLite文件中的全部历史内容都被清除,相关存储需要分别安排。

九、验收脱敏要检查最终保存值

建议用完全虚构的标记构造测试:嵌套对象、对象数组、JSON字符串、非JSON文本、位置参数、URL参数和响应中的敏感字段。

验收看的是最终存储和导出结果,不能只检查mask函数是否存在。还要核对日志查看权限、异常文本及截图分享流程。

一套可用的日志应该能回答“哪张单、哪个阶段、什么错误”,同时按约定控制敏感内容。通用脱敏函数与接口专属规则一起检查,才知道哪些入口已经覆盖、哪些仍需补上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询