2、字段级加密的典型架构

做字段级加密,第一个要回答的问题是:加密逻辑放哪?

我见过不少团队一上来就选数据库内置加密,结果上线后发现查询被拖慢30%,业务方差点掀桌子。也有团队全堆在应用层,后来换了一个框架,所有加密代码都要重写,教训深刻。

说白了,加密层选错了位置,后面再优化缓存都是亡羊补牢。这一节我们把这三种典型架构掰开揉碎讲清楚。

字段级加密三种架构对比 应用程序层 业务代码 (加密 / 解密逻辑) ORM / DAO 层 (字段拦截器) 数据库连接池 索引失效风险 缓存穿透风险 数据库层 透明数据加密(TDE) (全表/表空间加密) 字段级加密函数 (MySQL AES_ENCRYPT / PG pgcrypto) 存储引擎 / 文件系统 索引使用受限 迁移成本高 代理层 反向代理 / 网关 (如 Envoy / Kong) 加密代理中间件 (透明拦截 SQL) 缓存层(加密结果 / 字典) 网络延迟增加 故障定位难 蓝色系 = 应用程序层 紫色系 = 数据库层 青色系 = 代理层 红/橙/绿块 = 常见风险与注意事项

应用程序层加密:灵活但包袱重

这是最直接的方案。你在业务代码里拿着明文,调加密库,塞进数据库。查询时再反着来一遍。

在我手上,这种架构最适合的场景:加密字段少(≤5个)、查询模式简单(只按ID查)、业务需要灵活变更加密策略。

优点也很明显:

  • 加密算法随便换,今天AES-256明天SM4都行,数据库完全不知情。
  • 密钥管理可以做成独立的服务,不和数据库绑定。
  • 可以针对不同字段用不同密钥,甚至按用户粒度加密——我做过一个医疗项目,病历字段用患者ID+日期作为附加密钥,细粒度到每行。

但缺点……嗯,你想想看。每一处查询都可能触发解密,索引几乎作废。 更重要的是,一旦换了ORM框架或业务重构,加密代码要全量迁移。我曾经在一个旧项目里看到三个不同版本的加密实现混在代码里,有的用Java原生Cipher,有的用Hibernate拦截器,还有的直接在getter/setter里写——这简直是维护地狱。

避坑指南: 我曾经在一个高并发登录系统里用应用层加密存用户手机号。上线第一天就炸了——每次登录要解密手机号去匹配,数据库连接池直接打满。后来我们不得不在应用层前面加了一个Redis缓存明文映射,才算扛住。切记:应用层加密必须搭配写穿透缓存,否则查询性能不堪设想。

数据库层加密:省事但死板

数据库层加密又分两种:一种是全表/表空间加密(TDE),对应用完全透明;另一种是字段级加密函数,比如MySQL的AES_ENCRYPT()、PG的pgcrypto。

TDE保护的是静止数据——磁盘文件被拖走也读不了,但查询时数据库会把数据自动解密到内存,所以对应用层来说纯明文操作。但注意:它不防DBA,DBA有权限直接看内存。

字段级加密函数则更接近应用层加密——只在入库/出库时加解密,索引也是碎的。但好处是不用改业务代码,写一条SQL就能搞定。我见过一个金融项目,所有敏感字段都用MySQL的AES_ENCRYPT在存储过程里处理,后来要换成硬件加密机,改起来差点把存储过程全重写。

维度TDE(透明数据加密)字段级加密函数
对应用透明完全透明需要SQL改写
索引支持索引正常索引失效
DBA可读可读不可读
加密粒度表/表空间字段级
密钥管理数据库自带手动管理
迁移成本低(开关即可)高(需改SQL)

我的建议: 能用TDE解决的合规需求(如等保三级要求数据加密存储)就用TDE,别整花活。真正的字段级加密需求很少需要在数据库层做——它把索引和查询复杂度的坑全踩了,收益却一般。

代理层加密:解耦但引入新隐患

代理层听起来很美:应用无感知,加密逻辑从代码里抽出来,放到一个中间件里。就像加了一个“加密网关”,SQL先过它,再转给数据库。

市面上有开源方案,比如Encryption Proxy、ShardingSphere的加密功能,也有公司自己用Netty写一个。我个人更喜欢ShardingSphere的原因就是它内置了加密字典,可以缓存常见加密结果,配合Redis能大大降低重复计算。

但代理层有个致命问题:它成了单点故障和性能瓶颈。

实际案例: 我参与的一个电商系统,峰值QPS 1.2万,用代理层做手机号加密。代理层部署了3台,正常情况延迟增加不到2ms。但有一次代理层缓存热点键失效,所有请求直接穿透到数据库,代理层CPU被打到100%,导致全站慢查。后来我们不得不做熔断——加密失败时允许明文直连,用合规代价换可用性。

代理层的优缺点我用一个表讲清楚:

优点缺点
业务代码零侵入增加网络跳数(1~5ms)
加密策略集中管理代理成为性能和故障单点
便于灰度切换SQL解析复杂,易出bug
可复用缓存层运维成本高(多一个中间件)
支持多种数据库故障定位困难(丢包还是加密错?)

注意: 代理层加密最怕“透明的”——你以为无感,实际上SQL兼容性会打折扣。我见过一个项目用ShardingSphere的加密功能,结果LIKE查询加密后的密文直接报废,业务方只能改用精确匹配。所以测试阶段一定要把所有查询场景都覆盖到。

怎么选?我个人的决策框架

其实这三种架构不是互斥的。我做过几个成功的案例,都是“应用层+代理层混搭”:

  • 核心敏感字段(身份证、手机号)交给代理层统一加密,业务代码不动。
  • 内部标识字段(用户ID的hash值)在应用层用简单摘要算法处理,用来做索引。
  • 数据库层只用TDE兜底防丢盘。

说到底,没有银弹。你选哪个架构,取决于你的合规要求、查询模式、运维能力。三者权重不同,选择就不同。下个环节我们专门讲缓存加速怎么和这些架构配合,但那是后话——先把这个框架刻在脑子里,后面的优化才有的放矢。