


























以我们系统的数据表levy_merchant_relation为例,该数据表存储的是商户服务商关联关系。下面是与之对应的 LevyMerchantRelation 实体类结构,除了包括商户与服务商相关字段,还包括HTTP接口通信的秘钥和口令,如RSA公私钥、加密秘钥。
LevyMerchantRelation {id, merId, merName, levyId, levyName, levyMerId, levyMerName, interfaceKey, publicKey, privateKey, loginPassword, memo, createTime, updateTime}
本文要说的是这些秘钥字段数据。
这些秘钥数据,尤其是RSA秘钥,有两个特征:
这些秘钥数据会对系统带来如下伤害:
作为RPC传输的LevyMerchantRelationDTO,其结构不能直接是LevyMerchantRelation实体类的“副本”,而要排除掉秘钥字段,毕竟,90%的调用方是使用relation关系,而不需要秘钥数据。另外,对于那些需要秘钥数据的功能,如页面的CRUD,则定义单独的秘钥DTO。是的,仅包含秘钥字段。
LevyMerchantRelation {id, merId, merName, levyId, levyName, levyMerId, levyMerName, interfaceKey, publicKey, privateKey, loginPassword, memo, createTime, updateTime}
⬇ ⬇ ⬇
LevyMerchantRelationDTO {id, merId, merName, levyId, levyName, levyMerId, levyMerName, memo, createTime, updateTime}
ApiSecretDTO {interfaceKey, publicKey, privateKey, loginPassword}
一分为二后的两个DTO,一个仅包含业务字段,一个仅包含秘钥字段,职责清晰,边界分明,各司其职。
对应的服务接口应做相应拆分,确保"按需知密"的安全原则。
有了上面RPC传输层的数据隔离,LevyMerchantRelationDTO 本身不用考虑了。我们需要考虑的,是entity和ApiSecretDTO等包含秘钥的POJO。
我们在kibana日志平台经常看到长长的秘钥串,像金灿灿的油菜花田里一株突兀的、傲慢的绿草,它肆意摇曳,便将整片田野的和谐平衡,轻易撕开一道口子。

如何解决呢?
取决于我们打印日志的方式。
不外乎如下2种:
针对方式一,重写entity等模型类的 toString() 方法,在拼接字符串时去掉秘钥field。
import lombok.Data;
@Data
public class LevyMerchantRelation {
...
@Override public String toString() {
return "LevyMerchantRelation{" +
...
", interfaceKey='" + StringUtils.length(interfaceKey) + " characters'" +
", publicKey='" + StringUtils.length(publicKey) + " characters'" +
", privateKey='" + StringUtils.length(privateKey) + " characters'" +
...
'}';
}
}
针对方式二,则要说道说道了。一种办法是不用json序列化,改用方式一。但难免未来在系统迭代中又会出现这种方式的log.info。我们也不能将此纳入到团队编码规范里。毕竟,在log中查看经json序列化后的对象字符串,更利于肉眼识别关键信息。由此,JSONLog出现了。
JSONLog是什么?是一个自定义的工具类,是一个在IDE中键入”JSON“就能联想出来的工具类。
JSONLog的定义如下,它在将对象进行序列化时,过滤掉了 publicKey、privateKey、password等秘钥字段关键字。
这种从数据模型、接口设计到工具支持的全方位思考,正是构建安全、高性能系统的关键所在。
彼时的2025年5月份,消费券系统开始立项研发,在程序设计阶段,我们要为系统的两个关键参与者——消费企业 与 核销企业——设计数据表结构,我主张为两者分别创建各自的表,至于两者的营业资质信息,则存储到一个共同的营业资质表。看来,通过这种数据隔离方式的数据结构设计,亦可以有效规避这些营业资质信息在上述两方面对系统产生的伤害。 ————设若 levy_merchant_relation 这张表 不包含秘钥字段(关联关系与关联关系的秘钥分开存储),那么,就不存在 LevyMerchantRelation“因秘钥数据而对系统产生伤害”的事情。————anyway,从数据设计源头规避风险,也是很重要的一件事。
ref: ⬮ 如何在程序日志中不打印LevyMerchantRelation中的privateKey、publicKey这些大字符串field? ⬮ 程序日志优化:精准捕获与日志分级,践行数字低碳 ⬮ 20231130-调用上海银行timeout,哐哐报错。日复一日月复一月,我们视而不见。近几日日志文件动辄60~70G,我们的系统往往以日志量取胜。 <摘自公司内部confluence-wiki>
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。