定义@Sensitive注解标记字段,支持AES/SM4等算法及keyId;通过AttributeConverter或AOP实现加解密;集成KeyProvider对接KMS,确保数据库存二进制、日志脱敏、测试往返一致。

定义敏感字段加解密注解
创建一个自定义注解,用于标记需要加解密的字段。注解应支持运行时保留,并能指定加解密策略(如 AES、SM4)或密钥标识:
- 使用 @Target({ElementType.FIELD}) 限定只能标注在字段上
- 使用 @Retention(RetentionPolicy.RUNTIME) 确保可在运行时通过反射读取
- 可选添加 @Documented 和 @Inherited(通常不需要继承)
- 定义属性如 algorithm()(默认 "AES/GCM/NoPadding")、keyId()(用于密钥管理)、encryptBeforePersist() 和 decryptAfterLoad() 控制时机
实现加解密逻辑与密钥管理
编写统一的加解密工具类,集成国密 SM4 或国际 AES 等算法,并对接密钥管理系统(如 KMS、本地密钥池或 Spring Cloud Config):
- 避免硬编码密钥,采用 KeyProvider 接口抽象密钥获取逻辑,不同环境返回不同密钥实例
- 加解密方法需处理空值、字节数组编码(Base64 或 Hex)、异常吞吐(如解密失败返回 null 或抛出特定异常)
- 推荐使用 javax.crypto.Cipher + SecureRandom(GCM 模式需 IV);SM4 可用 Bouncy Castle 或国产密码库(如 gmhelper)
拦截持久化流程:JPA/Hibernate 方案
利用 Hibernate 的 @PrePersist、@PostLoad 回调,或更通用的 AttributeConverter 实现字段级自动编解码:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- AttributeConverter<String, String> 最简洁:将加密逻辑封装在 convertToDatabaseColumn / convertToEntityAttribute 中,配合 @Convert(converter = SensitiveFieldConverter.class) 标注字段
- 若需动态策略(如按 keyId 切换算法),可在 Converter 中通过反射读取字段上的注解元数据
- 注意:Converter 对基本类型(String/byte[])友好,对复杂嵌套对象不适用;此时建议改用实体生命周期监听器(@EntityListeners)
Spring AOP 方案(适用于 MyBatis 或非 JPA 场景)
当 ORM 框架不支持 AttributeConverter(如 MyBatis)时,可用 AOP 在 DAO 层织入加解密逻辑:
立即学习“Java免费学习笔记(深入)”;
- 定义切点匹配 save*、insert*、select* 等方法,参数或返回值含被注解的实体类
- 切面中递归扫描对象字段,识别 @Sensitive 注解,对 String/byte[] 类型字段执行对应加解密
- 注意深拷贝与不可变性:避免修改原始对象,建议返回新对象或使用 @Accessors(fluent = true) 配合 Builder 模式
- 性能敏感场景下,可结合 CGLIB 代理或编译期注解处理器(APT)生成静态代码,规避反射开销
安全与工程实践要点
自动加解密不是银弹,需兼顾安全性、可观测性和可维护性:
- 数据库字段类型应为 VARBINARY 或 TEXT(加密后是二进制或 Base64 字符串),禁止明文索引
- 日志脱敏:确保 toString()、JSON 序列化、审计日志中敏感字段已解密或屏蔽,可配合 Jackson 的 @JsonSerialize 定制序列化器
- 单元测试必须覆盖加解密往返一致性(加密 → 存库 → 查询 → 解密 → 值相等),并验证异常路径(如密钥缺失、损坏密文)
- 上线前做加密字段查询兼容性评估:LIKE 模糊查、ORDER BY、GROUP BY 将失效,需改用应用层过滤或引入搜索中间件(如 Elasticsearch)

















