HTTPS之外的响应加密-GCM序列化与处理器顺序

HTTPS 之外的响应加密:GCM、序列化与处理器顺序

技术背景: HTTPS 保护传输通道,但数据到达代理、网关或终端后仍然是明文。某些高敏业务会进一步要求响应体应用层加密,这与替代 HTTPS 是两回事。

应用层加密必须处理随机 IV、认证标签、序列化顺序、密钥分发和错误响应;如果先加密后修改响应,或重复使用 nonce,安全性会直接失效。

MetaLite 在外部响应处理器中统一完成序列化后的 GCM 加密,避免业务接口自行处理。本文先说明额外加密的适用场景,再结合处理器顺序验证边界。

一、应用层响应加密解决什么、不解决什么

网关接口统一返回 Resp,其中可以同时存在:

text 复制代码
data         明文业务对象
encryptData  加密后的字符串
code/message 业务状态

启用响应加密后,处理链执行:

text 复制代码
业务方法返回 Resp
  → 序列化 data
  → 加密写入 encryptData
  → 设置 HTTP 状态
  → 记录响应日志
  → 清除 data
  → 返回调用方

调用方仍能读取 code 和 message,再按约定解密 encryptData。

二、哪些响应会被加密

ApiRespEncryptHandler 只处理满足三项的结果:

  1. 请求参数属于 ExternalReq
  2. 结果属于 Resp 且 data 非空;
  3. 当前 appId 的调用方配置要求加密。

健康检查、第三方回调等没有使用 ExternalReq 的特殊接口不会进入这条逻辑。

错误响应如果 data 为 null,也不会产生 encryptData。协议设计需要确保错误 message 中不包含本应加密的敏感数据。

三、当前支持哪些算法

执行分支支持:

text 复制代码
SM4-GCM
SM4-CBC
AES-GCM
AES-CBC

且当前只支持对称加密类型。

后台配置注释即使出现更广的算法名称,也不能证明响应处理器已经实现;运行时遇到其他类型或算法会抛出 ServiceException。

这也是配置后台必须与执行分支共享枚举和校验的原因。

四、为什么优先考虑 GCM

GCM 属于 AEAD 模式,同时提供:

  • 机密性;
  • 完整性校验;
  • 篡改检测。

CBC 只解决机密性,还需要独立 MAC 并采用 Encrypt-then-MAC 才能可靠检测篡改。

如果 CBC 工具只返回 IV + 密文而没有认证标签,调用方无法安全区分"密文被修改"和"解密后恰好得到垃圾数据"。

因此新协议通常优先使用 AES-GCM 或 SM4-GCM,并保证每次加密使用唯一随机 nonce/IV。

五、为什么不能先清 data 再加密

加密处理器从 resp.data 获取明文:

java 复制代码
String plaintext = FastJson.obj2Json(resp.getData());

如果清理处理器先执行,得到的只能是 null。

MetaLite 使用 @Order 让加密处理器早于明文清理处理器,处理器链按升序执行。最终清理器检查 encryptData 已生成后才设置:

java 复制代码
resp.setData(null);

这体现了有序处理器链的价值:加密、状态、日志和清理不是彼此独立的几个切面,它们有数据依赖。

六、当前为什么会在日志中保留明文

处理顺序把响应日志放在明文清理之前,源码注释明确表示为了调试记录完整明文。

这意味着外部响应虽然不再包含 data,应用日志仍可能保存敏感业务对象。

如果应用层加密的威胁模型包含"日志平台或运维访问不应看到明文",当前顺序就破坏了目标。

更安全的日志策略是:

  • 记录 code、耗时、TraceId 和数据摘要;
  • 对允许字段脱敏;
  • 敏感接口完全不记录 body;
  • 需要问题定位时使用受控采样和临时开关;
  • 不记录密钥、明文或可重放请求。

调试便利不能默认高于数据最小化原则。

七、应用层加密不等于签名

响应密文即使使用 GCM,也只证明持有同一密钥的一方生成了合法认证标签。

在多调用方共享密钥、密钥权限过宽或需要不可否认性的场景,还要单独设计身份认证与签名。

请求侧的摘要签名、时间戳和响应加密解决不同问题:

text 复制代码
调用方认证:谁发起请求
防重放:请求是否过期或重复
响应加密:谁能读取 data
响应完整性:内容是否被改动

不能因为返回了 encryptData 就省略 HTTPS、调用方认证或重放防护。

八、密钥如何按调用方隔离

处理器按 appId 读取调用方缓存中的:

text 复制代码
encryptType
encryptAlgorithm
encryptSecret

为不同调用方配置不同密钥,可以缩小单个密钥泄漏影响范围。

但当前密钥作为调用方实体字段在数据库、缓存和管理链路中流转。完整治理还需要:

  • 密钥管理系统托管;
  • 管理页面只显示掩码;
  • 日志与审计不保存密钥值;
  • 密钥版本;
  • 双密钥轮换窗口;
  • 使用权限与访问审计;
  • 泄漏后的快速吊销。

直接替换密钥会让调用方无法解密切换前在途响应,因此版本必须进入协议或双方切换流程。

九、序列化协议也属于加密契约

密文中的明文不是任意 Java 对象,而是 FastJson2 生成的 JSON。

调用方解密后还要知道:

  • 字符编码;
  • 时间格式;
  • long 的表示方式;
  • null 字段策略;
  • 字段命名;
  • JSON Schema 版本。

加密不会解决序列化兼容问题,反而让抓包无法直接观察内容。因此接口版本和测试向量更重要。

建议提供固定的请求、IV/nonce、密钥版本和期望密文示例,双方可以自动验证实现一致性,但生产请求必须使用新 nonce,不能复用测试向量。

十、应用层响应加密的验收清单

text 复制代码
只对明确调用方启用
优先使用 GCM 等 AEAD
每次 nonce/IV 唯一
密钥按调用方隔离并可轮换
加密成功后才清理 data
日志不保存敏感明文
错误响应不泄露业务数据
序列化格式有版本和测试向量
仍然使用 HTTPS

MetaLite 的处理器链已经把"序列化、加密、状态、日志、清理"的执行顺序显式化。

真正决定安全强度的,不只是算法名称,而是 nonce、密钥生命周期、日志策略和协议兼容是否一起闭环。

十一、处理器顺序需要一组不可交换测试

可以为同一个 Resp.data 构造四组回归:正常明文响应、启用 GCM、业务异常响应、序列化失败。测试不仅比较 encryptData 是否存在,还要确认加密前数据没有提前清空、失败响应是否按协议处理、日志中保留的是允许排查的内容而不是完整敏感明文。

再交换一次日志处理器与 ApiRespEncryptHandler 的顺序,观察日志内容变化。这个反例能直接说明 @Order 不是代码排版,而是响应安全协议的一部分。

若前端和网关使用不同序列化配置,即使密钥、IV 和算法都正确,解密后的字节也可能无法还原业务对象,因此测试向量必须固定序列化结果。


框架简介

MetaLite 是面向企业生产环境的新一代 Java 微服务技术底座。系列文章重点分享代码背后的设计思路、技术取舍与工程实践。

源码基线

JDK 21、Spring Boot 3.2.9、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.3,具体组件版本以项目 backend-bom 为准。

作者简介

15 年 Spring 体系企业级开发经验,专注于 Java 微服务架构、工程治理与生产实践。

持续更新

MetaLite 系列内容将持续更新,围绕核心设计、源码链路、技术取舍与生产实践展开。欢迎关注作者,及时获取后续内容。

在线演示

演示地址: https://admin.metalite.top/

演示账号: guess

演示密码: admin@2026

相关推荐
姚不倒2 小时前
HAProxy 系列(二):健康检查与 SSL 卸载 — 保障可用性与性能
运维·网络·网络协议·ssl·haproxy
Neighbor_OldY2 小时前
云上证书过期与HTTPS安全治理实战:证书到期没人管、自动化续期与证书链排查
安全·https·自动化
蕾米莉亚《'';2 小时前
ip与dns科普向
网络协议·tcp/ip
美酒没故事°2 小时前
是tls、https、waf
网络协议·http·https
hzxpaipai3 小时前
企业官网 Nginx 部署完整流程:HTTPS、301、静态缓存与日志配置
nginx·缓存·https
StevenSurpass5 小时前
智能工厂场景:FastPrintAgent 分布式打印中间件落地应用方案
分布式·mqtt·http·中间件·打印·fastreport
wixzjsh12 小时前
TCP通信与HTTP协议学习笔记:粘包、三次握手、四次挥手与C/S、B/S模型
学习·tcp/ip·http
一直C12 小时前
Linux网络编程|HTTP协议详解(报文、请求方法、状态码)
linux·http·wireshark·vim·visual studio
鲨鱼辣钊14 小时前
FastAPI进阶_Day21_WebSocket实时通讯实战
websocket·网络协议·fastapi