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

SpringBoot中,接口加解密

1、背景

在项目做等保,要求需要对接口数据进行加密,所做了调用方发送请求前,先对明文加密,然后发送密文,被调用方收到数据后,先进行解密,然后再进行处理。返回的结果同样也可以加密,被调用方将需要返回的数据进行加密,然后将密文返回给调用方,调用方收到后,再进行解密便得到明文。

2、解决方案

使用AES的方式对数据加密

AES介绍

  1. 对称加密
    加密与解密使用同一密钥,效率高但需安全分发密钥。
  2. 分组密码
    将明文分割为固定128位(16字节)的块独立处理。
  3. 密钥长度灵活
    支持128位、192位、256位三种长度,安全性依次递增(AES-128/192/256)

利用RequestBodyAdviceAdapter,继承这个类重写其beforeBodyRead方法,完成请求在进入方法前对参数解密

RequestBodyAdviceAdapter介绍

RequestBodyAdviceAdapter 是 Spring Framework 中用于拦截和处理 **@RequestBody 注解参数**的核心组件,属于 Spring MVC 的全局增强机制。它通过 AOP 思想实现对请求体的统一预处理,避免在 Controller 中重复编写与业务无关的逻辑(如解密、校验、日志记录等)

方法

调用时机

用途

返回值

supports()

请求进入时优先判断

决定当前 Advice 是否生效(如按包路径、注解过滤)

true:生效;

false:跳过

beforeBodyRead()

请求体被 HttpMessageConverter

读取

修改原始请求体(如解密、字符编码转换)

自定义的 HttpInputMessage

afterBodyRead()

请求体转换为 Java 对象

修改对象(如参数校验、字段注入)

处理后的 Java 对象

handleEmptyBody()

请求体为空时

处理空请求体场景(如设置默认值)

替代空体的对象

在数据返回时候需要加密,用到ResponseBodyAdvice

ResponseBodyAdvice 介绍

ResponseBodyAdvice 是 Spring MVC(4.1+)及 Spring Boot 中用于全局拦截并定制化处理响应体的核心接口,通常与 @ControllerAdvice@RestControllerAdvice 配合使用。它允许开发者在控制器方法执行后、响应数据写入 HTTP 响应体之前,对返回的数据进行统一处理,适用于多种通用场景(如数据包装、脱敏、日志记录等)。

  1. 定位与触发时机
    • 作用阶段:在控制器方法执行完毕且返回值被 HttpMessageConverter 序列化之前介入。
    • 触发条件:仅对标注 @ResponseBody@RestController 的控制器方法生效。
  1. 核心方法

方法

作用

参数说明

supports()

判断当前响应是否需被处理(返回 true

则触发 beforeBodyWrite

returnType:控制器返回类型;
converterType:消息转换器类型。

beforeBodyWrite()

实际处理响应体,可修改或替换原始返回值

body:原始返回值;
request/response:HTTP 请求/响应对象;

作用方法指定方案

1.用到了@RestControllerAdvice这个注解指定扫描包路径来实现,这样就需要supports()方法直接返回true

@ControllerAdvice(basePackages = "cn.shenzhihe.collection.controller")

2.如果想指定具体方法,可以自定义注解方式,在supports()方法下指定注解

@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return methodParameter.hasMethodAnnotation(Decrypt.class);}

3.代码实现

指定配置类讲AES注册到ioc

@Configuration
@EnableConfigurationProperties(SecureProperties.class)
public class SecureConfiguration {@Autowiredprivate SecureProperties secureProperties;@Beanpublic AES aes() {return SecureUtil.aes(this.secureProperties.getKey().getBytes(StandardCharsets.UTF_8));}
}

配置

@Getter
@Setter
@ConfigurationProperties("secure")
public class SecureProperties {/*** 秘钥(长度只能是 128、192或256位,一个普通字符是8位)*/private String key;
}

yml

secure:key: 1234567890123456

入参加密

/*** 请求到达controller中的方法之前,会拦截标注有 @Decrypt 注解或者指定包下的方法,负责将原始请求中的密文转换为明文*/
@ControllerAdvice(basePackages = "cn.shenzhihe.collection.controller")
public class DecryptRequestBodyAdvice extends RequestBodyAdviceAdapter {@Autowiredprivate AES aes;@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {// 注解方式//return methodParameter.hasMethodAnnotation(Decrypt.class);//路径方式直接返回truereturn true;}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {String encoding = "UTF-8";try {//①:获取http请求中原始的bodyString body = IOUtils.toString(inputMessage.getBody(), encoding);//②:解密body,使用AES算法解密,得到明文String decryptBody = aes.decryptStr(body);//将解密之后的body数据重新封装为HttpInputMessage作为当前方法的返回值InputStream inputStream = new ByteArrayInputStream(decryptBody.getBytes(encoding));return new HttpInputMessage() {@Overridepublic InputStream getBody() throws IOException {return inputStream;}@Overridepublic HttpHeaders getHeaders() {return inputMessage.getHeaders();}};} catch (Exception e) {// 如果解密失败,返回原始消息return inputMessage;}}
}


/*** 在结果返回给调用者之前,会拦截标注有@Encrypt 注解或者包下方法的方法,对接口的返回值进行处理,将其转换为密文*/
@ControllerAdvice(basePackages = "cn.shenzhihe.collection.controller")
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {@Autowiredprivate AES aes;private ObjectMapper objectMapper = new ObjectMapper();@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {// 注解方式//return methodParameter.hasMethodAnnotation(Decrypt.class);//路径方式直接返回truereturn true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if (body == null) {return body;}String result;if (body instanceof String) {result = (String) body;} else {//如果是对象,则转换为json字符串try {result = objectMapper.writeValueAsString(body);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}//加密返回return this.aes.encryptHex(result);}
}

两个注解一起使用,入参解密,返回加密

注解

/*** 接口方法上添加该注解,这表示这个接口的参数是被加密的,进入方法之前,参数会自动被解密*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Decrypt {
}

/*** 接口方法上添加该注解,则返回的结果,会自动加密*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Encrypt {
}

4.测试

@RestController
@RequestMapping("/secure")
@Slf4j
public class SecureController {/*** 参数加密测试,需要在方法上标注 @Decrypt 注解** @param body* @return*/// @Decrypt@PostMapping("/decryptTest")public List<String> decryptTest(@RequestBody List<String> body) {log.info("参数加密测试,请求参数:{}", body);return body;}// @Encrypt@GetMapping("/encryptTest")public List<String> encryptTest() {List<String> encyptList = new ArrayList<>();encyptList.add("1");encyptList.add("2");return encyptList;}
}

返回密文

解析密文

http://www.dtcms.com/a/336591.html

相关文章:

  • C语言课程开发
  • 【前端基础】flex布局中使用`justify-content`后,最后一行的布局问题
  • Java 基础 -- Java 基础知识
  • 2025-08-17 李沐深度学习18——循环神经网络基础
  • Spring Cloud系列—Seata部署
  • 照相机标定-动手学计算机视觉16
  • easya2a: 一键将 LangChain Agent 发布为 A2A 服务
  • Matlab数字图像处理——基于BM4D压缩感知的三维图像信号重构算法
  • 知识点汇集-web
  • 第三十八天(Node.JS)
  • 【LeetCode 热题 100】(八)二叉树
  • 如何使用java写一个agent
  • 说一下分离读写
  • c_str()函数的详细解析
  • 力扣438:找到字符串中所有的字母异位词
  • ACCESS/SQL SERVER保存软件版本号为整数类型,转成字符串
  • 第13章《远程处理:一对一及一对多》——PowerShell Remoting 学习笔记
  • Windows_Server软件定义网络架构
  • MXFP4量化:如何在80GB GPU上运行1200亿参数的GPT-OSS模型
  • 编程算法实例-阶乘
  • 天地图开发的优点
  • Steam 上传游戏包体操作步骤
  • Win11 文件资源管理器预览窗格显示 XAML 文件内容教程
  • K8S集群环境搭建(一)
  • STL 容器
  • 华东师范上海AiLab商汤!NaviMaster:学习适用于GUI和具身导航任务的统一策略
  • React学习(四)
  • 计算机视觉(一):nvidia与cuda介绍
  • 王树森深度强化学习DRL(一)RL基本概念+价值学习
  • 基于51单片机汽车自动照明灯超声波光敏远近光灯设计