核心是通过自定义注解(@DecryptRequest/@EncryptResponse)标记方法,结合HandlerMethodArgumentResolver实现请求自动解密、ResponseBodyAdvice实现响应自动加密,配合密钥动态管理与安全异常处理,达成低侵入、可复用的敏感接口加解密。

Java中通过自定义注解实现敏感接口的请求解密(DecryptRequest)与响应加密(EncryptResponse),核心在于结合Spring AOP或HandlerMethodArgumentResolver/ResponseBodyAdvice,对特定标注的方法自动处理加解密逻辑。关键不是“写个注解就完事”,而是注解作为标记,配合拦截机制完成统一、可复用的加解密流程。
定义自定义注解
先声明两个运行时保留的注解,用于标记控制器方法:
-
@DecryptRequest:标识该接口入参需先解密(如前端传来的AES密文) -
@EncryptResponse:标识该接口返回值需加密后再响应(如敏感字段AES加密后返回)
示例定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DecryptRequest {
String value() default ""; // 可扩展指定密钥ID或算法类型
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptResponse {
boolean includeNull() default false; // 是否加密null字段(可选)
}
实现请求自动解密(@DecryptRequest)
推荐使用 HandlerMethodArgumentResolver,在参数绑定前介入,识别带注解的方法并解密请求体(如JSON密文):
立即学习“Java免费学习笔记(深入)”;
- 重写
supportsParameter():判断当前参数是否属于被@DecryptRequest标记的方法且参数类型为String或具体DTO类 - 重写
resolveArgument():从HttpServletRequest读取原始body(注意避免多次读取),用AES/RSA等算法解密,再反序列化为目标对象 - 需配置
WebMvcConfigurer注册该resolver,确保优先级高于默认JSON解析器
注意:若前端用标准POST JSON密文,建议约定密文放在请求头(如 X-Encrypted-Body)或固定字段(如 {"data":"xxx"}),避免与常规参数冲突。
实现响应自动加密(@EncryptResponse)
使用 ResponseBodyAdvice 是更优雅的方式,在Controller返回后、序列化前修改响应体:
- 实现
supports():检查当前方法是否标注@EncryptResponse - 重写
beforeBodyWrite():对body对象进行加密(如对整个响应JSON字符串AES加密,或仅加密指定字段) - 可结合Jackson注解(如
@JsonIgnore)或自定义序列化器,区分敏感字段;也可直接加密最终JSON字符串,返回{"code":0,"data":"U2FsdGVkX1..."}
常见做法是封装一个 Encryptor 工具类,支持SM4/AES/GM/TLS密钥协商等,由注解属性(如 algorithm())动态选择策略。
安全与工程细节要点
实际落地需关注几个易忽略但关键的问题:
- 密钥管理:禁止硬编码密钥,应从配置中心或KMS获取,支持密钥轮换;解密失败必须明确报错(如400 + “Invalid encrypted data”),不暴露内部异常
- 幂等与性能:加解密是CPU密集型操作,避免在高并发场景下成为瓶颈;可考虑异步加解密(慎用,需保证顺序)或缓存解密结果(仅限无状态场景)
-
兼容性:加解密后响应格式要与前端约定一致(如是否仍保持
{"code":0,"data":{...}}结构),避免破坏现有SDK - 排除非敏感路径:在AOP或Advice中主动跳过健康检查、登录、静态资源等无需加解密的接口,提升效率
不复杂但容易忽略。


















