惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
Vercel News
Vercel News
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
N
News and Events Feed by Topic
Application and Cybersecurity Blog
Application and Cybersecurity Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 【当耐特】
WordPress大学
WordPress大学
Google Online Security Blog
Google Online Security Blog
博客园 - Franky
Attack and Defense Labs
Attack and Defense Labs
Help Net Security
Help Net Security
V
Visual Studio Blog
Jina AI
Jina AI
H
Heimdal Security Blog
小众软件
小众软件
O
OpenAI News
腾讯CDC
The Last Watchdog
The Last Watchdog
雷峰网
雷峰网
Cloudbric
Cloudbric
量子位
博客园_首页
The GitHub Blog
The GitHub Blog
L
LangChain Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
The Blog of Author Tim Ferriss
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Last Week in AI
Last Week in AI
V2EX - 技术
V2EX - 技术
Security Archives - TechRepublic
Security Archives - TechRepublic
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 司徒正美
M
MIT News - Artificial intelligence
大猫的无限游戏
大猫的无限游戏
T
Tor Project blog
C
CERT Recently Published Vulnerability Notes
W
WeLiveSecurity
B
Blog
C
Check Point Blog
TaoSecurity Blog
TaoSecurity Blog
T
Threatpost
Hugging Face - Blog
Hugging Face - Blog
Recent Announcements
Recent Announcements
Project Zero
Project Zero
Hacker News: Ask HN
Hacker News: Ask HN
U
Unit 42
Simon Willison's Weblog
Simon Willison's Weblog

博客园 - buguge

从 `int` 到 `Duration`:一个缓存 API 的三次演进教会我的事 最差实践(bad-practice):开发者在方法里直接实例化线程池对象,然后...(应用gg了) 【HttpClient最差实践(bad-practice)】开发者在 http 工具方法中直接实例化 HttpClient,然后…… Crypto、Cipher与Password:Java加密开发的三个核心概念 知识VS技能:如何优雅判空? 20260604SR超时问题排查 推敲见文章:从 `try..catch` 看异常日志打印的正确姿势 #解决问题要彻底# 慢SQL治理完成后,如何防止同类问题“死灰复燃”? 从合同甲方是荒谬的“JD”谈起:软件开发不应遗忘的“常识” 别留小尾巴/尽快剪掉小尾巴:从一次“ABA”字段重命名,谈谈“解决问题要彻底” 常见的OOM错误 ( OutOfMemoryError全类型详解) 开发者暴露了一个无需授权访问的裸接口,我问:如果有人暴力请求怎么办? 【SQL性能优化篇】有了!治理慢SQL“WHERE create_time ORDER BY id”的良药---规避“Using filesort”性能杀手 高效查询商户日终余额:一个SQL的优化实践 Hutool 的 `TimedCache` 到期会自动清理吗? ——————hutool cache的"惰性清理"和"定期清理" Fastjson枚举反序列化:当字符串不是枚举常量名时,会发生什么? fastjson-EnumDeserializer类及源码分析 随笔20260309:我们都是围城里的人 `UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only` 异常解析 认识2个单词:goal/target —————— 为什么Maven是 "goal" 而不是 "target"? 聚合系统设计:策略模式(Strategy Pattern)在银行通道对接场景中的应用 这样构建对象,太帅了!—— 阶梯式Builder模式与代码整洁之道 注意!字段数据类型不匹配,这个sql会很慢 还在用ArrayList?用HashSet吧!--性能对比 分页查询还在用create_time去做降序? 从 synchronized 到 ConcurrentHashMap:一个小小的并发控制策略升级优化,证明我还是初级程序员 面试题沟通整理 【研发笔记20260120】值得记录:靠谱程序员的回聘 未给entity的主属性赋值,Mybatisplus却抛出了type mismatch异常。——————分享一下Mybatisplus主键填充机制 在java中实现c#的int.TryParse方法 灵活用工平台-连续劳务所得税-计算器-工具类,拿走不谢 Apollo场景建议配置指南:充分发挥分布式配置中心优势
研发笔记:如何消除长字符串的秘钥数据对RPC负荷、日志量、系统安全所带来的伤害?
buguge · 2026-01-13 · via 博客园 - buguge

0x01. 秘钥数据特征

以我们系统的数据表levy_merchant_relation为例,该数据表存储的是商户服务商关联关系。下面是与之对应的 LevyMerchantRelation 实体类结构,除了包括商户与服务商相关字段,还包括HTTP接口通信的秘钥和口令,如RSA公私钥、加密秘钥。

LevyMerchantRelation ​{id, merId, merName, levyId, levyName, levyMerId, levyMerName, interfaceKey, publicKey, privateKey, loginPassword, memo, createTime, updateTime}

本文要说的是这些秘钥字段数据。

这些秘钥数据,尤其是RSA秘钥,有两个特征:

  1. 是比较长的字符串。
  2. 属于系统隐私数据。

这些秘钥数据会对系统带来如下伤害:

  1. 对于微服务架构系统来说,这些数据通过RPC传输,一来泄露了隐私数据,致使系统存在安全风险;其次,这些数据急剧增大RPC数据传输的payload(响应结果包含秘钥数据的list接口或page接口,所带来的影响尤其明显)。
  2. 程序日志方面,这些数据打印在日志文件里,一来泄露了隐私数据,致使系统存在安全风险;其次,这些大字符串数据会使日志体积变大。再者,当我们在通过分析日志来排查系统问题时,这些大字符串往往比较碍眼,会降低我们排查问题的效率。

0x02. 如何解决秘钥数据对系统产生的伤害?

⬮ 解决对RPC传输的伤害 ←RPC传输层的数据隔离

1. DTO职责分离设计:一分为二

作为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,一个仅包含业务字段,一个仅包含秘钥字段,职责清晰,边界分明,各司其职。

2. RPC接口的精细化设计

对应的服务接口应做相应拆分,确保"按需知密"的安全原则。

  • 对于查询接口,单独定义个获取秘钥的接口(如果需要的话),其他接口均返回 LevyMerchantRelationDTO。
  • 新增/修改接口则同时包含LevyMerchantRelationDTO和ApiSecretDTO这2个参数。通过RPC接口层面彻底隔离,把伤害降低至0。

⬮ 解决对日志的伤害

有了上面RPC传输层的数据隔离,LevyMerchantRelationDTO 本身不用考虑了。我们需要考虑的,是entity和ApiSecretDTO等包含秘钥的POJO。

我们在kibana日志平台经常看到长长的秘钥串,像金灿灿的油菜花田里一株突兀的、傲慢的绿草,它肆意摇曳,便将整片田野的和谐平衡,轻易撕开一道口子。

image

如何解决呢?

取决于我们打印日志的方式。

不外乎如下2种:

  • 方式一:log.info("XX服务商】-查询企业账户信息,接口入参:relation={}", levyMerchantRelation);  
  • 方式二:log.info("XX服务商】-查询企业账户信息,接口入参:relation={}", JSON.toJSONString(levyMerchantRelation));  

针对方式一,重写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等秘钥字段关键字。

0x03. 总结

这种从数据模型、接口设计到工具支持的全方位思考,正是构建安全、高性能系统的关键所在。

彼时的2025年5月份,消费券系统开始立项研发,在程序设计阶段,我们要为系统的两个关键参与者——消费企业 与 核销企业——设计数据表结构,我主张为两者分别创建各自的表,至于两者的营业资质信息,则存储到一个共同的营业资质表。看来,通过这种数据隔离方式的数据结构设计,亦可以有效规避这些营业资质信息在上述两方面对系统产生的伤害。 ————设若 levy_merchant_relation 这张表 不包含秘钥字段(关联关系与关联关系的秘钥分开存储),那么,就不存在 LevyMerchantRelation“因秘钥数据而对系统产生伤害”的事情。————anyway,从数据设计源头规避风险,也是很重要的一件事。

ref: ⬮ 如何在程序日志中不打印LevyMerchantRelation中的privateKey、publicKey这些大字符串field?   ⬮ 程序日志优化:精准捕获与日志分级,践行数字低碳   ⬮ 20231130-调用上海银行timeout,哐哐报错。日复一日月复一月,我们视而不见。近几日日志文件动辄60~70G,我们的系统往往以日志量取胜。  <摘自公司内部confluence-wiki>