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

springboot项目不同平台项目通过http接口AES加密传输

前言:

在公司协作开发的过程中,自己的项目是公共调用平台,也可以说是中转平台,供公司其他团队的项目进行接口调用。因为是不同团队项目之间的相互调用,所以不能通过openFeign远程调用。只能通过http远程调用,但是在http调用的过程中数据不能通过明文传输,这样是不安全的。所以下面演示如何使用AES秘钥,对接口数据进行加解密。

目录

一,引入maven依赖

二,生成AES对称秘钥

三,将控制台打印的秘钥保存,粘贴到yml文件中去

四,核心加解密工具类

五,封装统一返回对象工具类

5.1,校验重复请求工具类(可选,非必要)

六,接收加密后的数据请求接口(解密示例接口)

七,发送请求加密data业务数据(加密示例接口)

八,发送请求测试

九,升级拓展


一,引入maven依赖

        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.37</version></dependency>

二,生成AES对称秘钥

运行这一块代码输出秘钥:

@Testpublic void test() {byte[] keyBytes = SecureUtil.generateKey("AES").getEncoded();String keyStr = Base64.encode(keyBytes);   // 转 Base64 字符串,方便存配置System.out.println("AES 密钥:" + keyStr);}

三,将控制台打印的秘钥保存,粘贴到yml文件中去

四,核心加解密工具类

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Component
public class AesKit {@Value("${aes.key}")private String key;private SymmetricCrypto aes;@PostConstructpublic void init() {this.aes = new SymmetricCrypto(SymmetricAlgorithm.AES, Base64.decode(key));}public String encrypt(String plain) {return aes.encryptBase64(plain);}public String decrypt(String cipher) {return aes.decryptStr(cipher);}
}

五,封装统一返回对象工具类

import com.zqd.common.constant.HttpStatus;
import com.zqd.common.utils.uuid.IdUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;/*** 加密data业务数据响应实体类*/
@ApiModel(value = "返回对象",description = "返回结果"
)
@Data
public class EncryptionR<T> implements Serializable {private static final long serialVersionUID = 1L;/** 成功 */public static final int SUCCESS = HttpStatus.SUCCESS;/** 失败 */public static final int FAIL = HttpStatus.ERROR;@ApiModelProperty("返回code值")private int code;@ApiModelProperty("时间戳")private Long timestamp=System.currentTimeMillis();@ApiModelProperty("随机数")//如果生成uuid工具类用不了那就切换成你自己生成uuid的工具类private String nonce= IdUtils.fastSimpleUUID();@ApiModelProperty("返回提示信息")private String msg;@ApiModelProperty("返回数据")private T data;public static <T> EncryptionR<T> ok(){return restResult(null, SUCCESS, "操作成功");}public static <T> EncryptionR<T> ok(T data){return restResult(data, SUCCESS, "操作成功");}public static <T> EncryptionR<T> ok(T data, String msg){return restResult(data, SUCCESS, msg);}public static <T> EncryptionR<T> fail(){return restResult(null, FAIL, "操作失败");}public static <T> EncryptionR<T> fail(String msg){return restResult(null, FAIL, msg);}public static <T> EncryptionR<T> fail(T data){return restResult(data, FAIL, "操作失败");}public static <T> EncryptionR<T> fail(T data, String msg){return restResult(data, FAIL, msg);}public static <T> EncryptionR<T> fail(int code, String msg){return restResult(null, code, msg);}private static <T> EncryptionR<T> restResult(T data, int code, String msg){EncryptionR<T> apiResult = new EncryptionR<>();apiResult.setCode(code);apiResult.setData(data);apiResult.setMsg(msg);return apiResult;}
}
5.1,校验重复请求工具类(可选,非必要)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import java.time.Duration;@Component
public class HttpRequestCheck {@Autowiredpublic RedisTemplate redisTemplate;/*** 校验重复请求* @param timestamp 时间戳* @param nonce 随机数* @return*/public  void isRepeatSubmit(Long timestamp, String nonce) {long now  = System.currentTimeMillis();long diff = Math.abs(now - timestamp);// 允许 60 秒误差(发送请求到接收到请求的时间差)if (diff > 60000) {throw new RuntimeException("请求已过期");}// 防止重复 nonce:Redis 查重String key = "nonce:" + nonce;if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {throw new RuntimeException("重复请求");}redisTemplate.opsForValue().set(key, "1", Duration.ofMinutes(5));}
}

六,接收加密后的数据请求接口(解密示例接口)

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.zqd.common.annotation.Anonymous;
import com.zqd.common.constant.HttpStatus;
import com.zqd.common.exception.ServiceException;
import com.zqd.system.serverutils.dome2.AesKit;
import com.zqd.system.serverutils.dome2.EncryptionR;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Objects;@RestController
@RequestMapping("/domeD")
@Api(tags = "测试D")
public class DomeTestControllerB {private static final Logger log = LoggerFactory.getLogger(DomeTestController.class);@AutowiredAesKit aesKit;//    @Autowired
//    HttpRequestCheck httpRequestCheck;@PostMapping("/testD")@ApiOperation(value = "内测试D")@Anonymouspublic EncryptionR queryIncompleteExamination(@RequestBody @Validated String cipher) {EncryptionR req = JSONUtil.toBean(cipher, EncryptionR.class);if(!Objects.equals(HttpStatus.SUCCESS, req.getCode())){throw new ServiceException("请求失败:"+req.getMsg());}//校验重复请求(可选)
//        httpRequestCheck.isRepeatSubmit(req.getTimestamp(), req.getNonce());log.info("接收到的密文:{}", req.getData());String plain = aesKit.decrypt(req.getData().toString());log.info("解密后的明文:{}", JSON.toJSONString(plain));String resp = JSONUtil.toJsonStr("哈哈哈111111111111返回");// 直接返回其他密文字符串return EncryptionR.ok(aesKit.encrypt(resp));}}

七,发送请求加密data业务数据(加密示例接口)

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.zqd.common.annotation.Anonymous;
import com.zqd.common.constant.HttpStatus;
import com.zqd.common.exception.ServiceException;
import com.zqd.system.serverutils.dome.dome.AesKit;
import com.zqd.system.serverutils.dome.dome.EncryptionR;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Objects;@RestController
@RequestMapping("/domeE")
@Api(tags = "测试E")
public class DomeTestControllerA {@AutowiredAesKit aesKit;@PostMapping("/testE")@ApiOperation(value = "内测试E")@Anonymouspublic EncryptionR<String> queryIncompleteExamination() {// 1. 构造业务 JSONString json = JSONUtil.toJsonStr("哈哈哈哈");// 2. 加密String cipher = aesKit.encrypt(json);// 3. 发 HTTP,直接发字符串String respCipher = HttpRequest.post("http://localhost:****/game/domeD/testD")//请求地址换成你自己的目标地址url.body(JSON.toJSONString(EncryptionR.ok(cipher))).execute().body();EncryptionR bean = JSONUtil.toBean(respCipher, EncryptionR.class);if(!Objects.equals(HttpStatus.SUCCESS, bean.getCode())){throw new ServiceException("请求失败:"+bean.getMsg());}// 4. 解密 B 的返回String plainResp = aesKit.decrypt(bean.getData().toString());return EncryptionR.ok(plainResp);}}

八,发送请求测试

在DomeTestControllerA中加密业务数据发送请求到DomeTestControllerB解密数据。

DomeTestControllerA:

DomeTestControllerB:

后面DomeTestControllerB响应的业务数据也需要加密响应给DomeTestControllerA,DomeTestControllerA以相同的方式解密即可。

到此就可以实现接口数据的加解密过程了。

九,升级拓展

如果你想实现校验重复请求,打开这行代码即可。

如果觉得粒度不够,没有细粒度到用户id。那么你也可以在我的代码基础上修改。

修改步骤:

1,在HttpRequestCheck中添加属性userId

2,在HttpRequestCheck重载一个isRepeatSubmit方法,入参添加一个用户id。redsi缓存的key在随机数前面加上用户id即可

3,根据你的业务需求调用校验方法

到此结束!!!

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

相关文章:

  • AR技术赋能电力巡检:智能化升级的“秘密武器”
  • MicroVM-as-a-Service 后端服务架构设计与实现
  • 顺序表插入删除
  • 常见的Jmeter压测问题
  • OpenCV 视频处理全解析
  • 力扣-295.数据流的中位数
  • 11、C 语言字符串函数总结
  • OpenCV 高斯模糊降噪
  • npm删除包
  • PyCharm性能优化与大型项目管理指南
  • C++:浅尝gdb
  • YouBallin正式上线:用Web3重塑创作者经济
  • 一种适用于 3D 低剂量和少视角心脏单光子发射计算机断层成像(SPECT)的可泛化扩散框架|文献速递-深度学习人工智能医疗图像
  • HTML <link rel=“preload“>:提前加载关键资源的性能优化利器
  • 【AAAI2025】计算机视觉|即插即用|FSTA:炸裂!这个即插即用模块,让你的SNN性能起飞!
  • DeepSeek补全IBM MQ 9.4 REST API 执行命令的PPT
  • 爬虫数据存储全攻略:从 Robots 协议到文件存储
  • 【深度学习新浪潮】VGGT待提升点分析及解决方案的思考
  • 基于大语言模型的爬虫数据清洗与结构化
  • pdf文件流或者本地文件读取
  • 掌握MATLAB三维可视化:从基础到实战技巧
  • OpenCV Canny 边缘检测
  • 【js】让项目支持倾听和朗读AI技术
  • OpenCV图像平滑处理方法详解
  • tp5集成elasticsearch笔记
  • 开疆智能Ethernet转ModbusTCP网关连接UR机器人配置案例
  • ComfyUI工作流不动了?
  • OpenCV 形态学操作
  • Spring AI PagePdfDocumentReader 全解析:基于 Apache PdfBox 的按页 PDF 读取实战
  • COLMAP进行密集重建,三维重建的步骤