当前位置: 首页 > news >正文

Spring Boot 一个注解搞定「加密 + 解密 + 签名 + 验签」

Spring Boot 一个注解搞定「加密 + 解密 + 签名 + 验签」

本文基于 Spring Boot 3.x,通过一个自定义注解 + AOP,一行注解即可给任何 Controller 方法加上
请求解密 → 验签 → 响应加密 → 加签 的完整链路,并可直接拷贝到生产环境使用。

一、最终效果

@PostMapping("/order")
@ApiSecurity(decryptRequest = true, encryptResponse = true)   // ← 就这么一行
public OrderResp createOrder(@RequestBody OrderReq req) {return service.create(req);
}
  • 请求体:RSA 加密后的 AES 密钥 + AES 加密后的业务 JSON + 签名
  • 框架自动完成 解密 → 验签 → 业务处理 → 响应加密 → 加签
  • 零侵入,老接口想加安全,贴一个注解即可。

二、传输对象

@Data
public class ApiSecurityParam {private String appId;      // 应用标识private String key;        // RSA 加密后的 AES 密钥(Base64)private String data;       // AES 加密的业务 JSON(Base64)private String sign;       // 签名private String timestamp;  // 防重放private String nonce;      // 防重放
}

三、核心注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiSecurity {boolean decryptRequest()  default false; // 请求体是否解密boolean encryptResponse() default false; // 响应体是否加密boolean sign()            default true;  // 是否验签/加签
}

四、AOP 切面(RequestBodyAdvice + ResponseBodyAdvice)

同时解决 InputStream 只能读一次 的问题。

4.1 解密 & 验签 RequestBodyAdvice

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DecryptRequestAdvice implements RequestBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) {return methodParameter.hasMethodAnnotation(ApiSecurity.class)&& methodParameter.getMethodAnnotation(ApiSecurity.class).decryptRequest();}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage,MethodParameter parameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) {return body;}@SneakyThrows@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage,MethodParameter parameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) {String body = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8);ApiSecurityParam param = JSON.parseObject(body, ApiSecurityParam.class);// 1. 防重放校验(timestamp、nonce)checkReplay(param);// 2. RSA 私钥解密 AES 密钥String aesKey = RSAUtil.decryptByPrivateKey(param.getKey(), RsaKeyHolder.PRIVATE_KEY);// 3. AES 解密业务 JSONString json = AESUtil.decrypt(param.getData(), aesKey);// 4. 验签boolean ok = RSAUtil.verify(json + param.getTimestamp() + param.getNonce(),RsaKeyHolder.PUBLIC_KEY, param.getSign());if (!ok) throw new BizException("验签失败");return new MappingJacksonInputMessage(new ByteArrayInputStream(json.getBytes()),inputMessage.getHeaders());}
}

4.2 加密 & 加签 ResponseBodyAdvice

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType,Class<? extends HttpMessageConverter<?>> converterType) {ApiSecurity anno = returnType.getMethodAnnotation(ApiSecurity.class);return anno != null && anno.encryptResponse();}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {String json = JSON.toJSONString(body);// 1. 随机 AES 密钥String aesKey = AESUtil.randomKey(128);// 2. AES 加密响应String data = AESUtil.encrypt(json, aesKey);// 3. RSA 公钥加密 AES 密钥String encKey = RSAUtil.encryptByPublicKey(aesKey, RsaKeyHolder.PUBLIC_KEY);// 4. 生成签名String sign = RSAUtil.sign(json, RsaKeyHolder.PRIVATE_KEY);ApiSecurityParam resp = new ApiSecurityParam();resp.setKey(encKey);resp.setData(data);resp.setSign(sign);resp.setTimestamp(String.valueOf(System.currentTimeMillis()));return resp;}
}

五、工具类速览

  • RSAUtilencrypt/decrypt + sign/verify
  • AESUtilencrypt/decrypt 支持 PKCS5Padding
  • RsaKeyHolder:从 application.yml 或 KMS 读取公私钥

六、性能 & 安全小贴士

建议
对称加密AES-128-CBC/PKCS5Padding
非对称RSA-2048
防重放timestamp ±5 min + nonce 一次性
密钥轮换每日定时任务刷新 RSA 密钥对
性能AES 每次随机 IV,RSA 只加密 128bit 密钥,无压力

七、小结

通过以上 一个注解 + 两个 Advice,在 Spring Boot 中实现 企业级安全传输

  • 0 侵入:老接口贴注解即可
  • 高可扩展:支持 GET/POST、Header 传参、自定义算法
  • 已落地:可直接封装为 spring-boot-starter-security-api,全公司复用。

源码示例已上传 GitHub:
https://github.com/your-org/spring-boot-api-security-starter

http://www.lryc.cn/news/594403.html

相关文章:

  • 零基础 “入坑” Java--- 十三、再谈类和接口
  • KOSMOS-2: 将多模态大型语言模型与世界对接
  • 算法训练营day25 回溯算法④ 补充联系题目 332.重新安排行程、51. N皇后、37. 解数独
  • PID控制原理分析及应用(稳态误差详细分析)(一)
  • 30天打牢数模基础-卷积神经网络讲解
  • STM32-第八节-TIM定时器-4(编码器接口)
  • 2025 年科技革命时刻表:四大关键节点将如何重塑未来?
  • 【高等数学】第四章 不定积分——第五节 积分表的使用
  • 【实战1】手写字识别 Pytoch(更新中)
  • RTC外设详解
  • Vuex 核心知识详解:Vue2Vue3 状态管理指南
  • Qt--Widget类对象的构造函数分析
  • 【vue-7】Vue3 响应式数据声明:深入理解 reactive()
  • 2024年青少年信息素养大赛图形化编程小低组初赛真题(含答案)
  • ZooKeeper学习专栏(二):深入 Watch 机制与会话管理
  • C语言:深入理解指针(2)
  • 网络地址和主机地址之间进行转换的类
  • 剑指offer66_不用加减乘除做加法
  • Spring Boot 订单超时自动取消的 3 种主流实现方案
  • 腾讯二面手撕题:BatchNorm和LayerNorm
  • 08_Opencv_基本图形绘制
  • 学成在线项目
  • Eureka+LoadBalancer实现服务注册与发现
  • 限流算法与实现
  • Shell脚本-tee工具
  • Kafka 在分布式系统中的关键特性与机制深度解析
  • kotlin Flow快速学习2025
  • PostgreSQL实战:高效SQL技巧
  • 【LeetCode刷题指南】--反转链表,链表的中间结点,合并两个有序链表
  • 基于单片机无线防丢/儿童防丢报警器