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.pswp.cn/pingmian/93090.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93090.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93090.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

推薦5個網頁模板資源網

1. 企業模板官方網站&#xff1a; http://www.qimoban.com介紹&#xff1a;企業模板(qimoban.com )是一個專注于提供豐富多樣的企業模板的優質平臺&#xff0c;致力于為企業和個人打造高效、專業、個性化的模板獲取渠道。該平臺提供海量的企業模板資源&#xff0c;涵蓋企業官網…

Redis持久化機制(RDB AOF)

1. RDB RDB 持久化是把當前進程數據生成快照保存到硬盤的過程&#xff0c;觸發 RDB 持久化過程分為手動觸發和 自動觸發&#xff0c;存儲的是二進制數據。 1.1 手動觸發 使用 save 和 bgsave 命令觸發&#xff1a; save&#xff1a;Redis服務主進程阻塞式執行持久化操作&…

【css】讓瀏覽器支持小于12px的文字

【css】讓瀏覽器支持小于12px的文字.demo {display: inline-block;/** 使用Webkit引擎的變換屬性&#xff08;主要針對舊版Safari/Chrome&#xff09; **/-webkit-transform: scale(0.8); }注意&#xff1a;display: inline-block; 一定要加上&#xff01;1.transform: scale(…

機器學習-基礎入門:從概念到核心方法論

在人工智能飛速發展的今天&#xff0c;機器學習作為其核心技術&#xff0c;正深刻改變著我們的生活與工作。從 AlphaGo 戰勝圍棋世界冠軍&#xff0c;到日常的智能推薦、人臉識別&#xff0c;機器學習的應用無處不在。本文將從基礎概念出發&#xff0c;帶你系統了解機器學習的核…

《Leetcode》-面試題-hot100-動態規劃

題目列表 70. 爬樓梯 簡單難度 leetcode鏈接 118. 楊輝三角 簡單難度 leetcode鏈接 198. 打家劫舍 中等難度 leetcode鏈接 279.完全平方數 中等難度 leetcode鏈接 322.零錢兌換 中等難度 leetcode鏈接 139.單詞拆分 中等難度 leetcode鏈接 300.最長遞增子序列 中等難度 l…

數巔中標中建科技AI知識庫項目,開啟建筑業數智化新篇章

AI正以前所未有的迅猛態勢滲透進建筑業的每一處脈絡。在這場數智化轉型浪潮中&#xff0c;AI技術如何與建筑業基因深度融合&#xff1f;如何充分釋放數據價值&#xff1f;近日&#xff0c;數巔成功中標中建科技集團有限公司“企業AI知識庫研發”項目&#xff0c;這一“大語言模…

想要PDF翻譯保留格式?用對工具是關鍵

嘿&#xff0c;朋友&#xff01;最近有沒有被PDF翻譯的事兒搞得焦頭爛額呀&#xff1f;尤其是碰到韓文PDF文件的時候&#xff0c;是不是更頭疼了&#xff1f;別擔心&#xff0c;我最近也遇到了類似的問題&#xff0c;試了不少軟件&#xff0c;發現有五款軟件在處理韓文PDF翻譯時…

【MySQL?】服務器安裝 MySQL 及配置相關操作

1. 安裝 MySQL 在安裝 MySQL 時&#xff0c;如果使用官方 RPM 源&#xff0c;會遇到 GPG 密鑰驗證失敗的錯誤&#xff0c;可以按照以下步驟解決&#xff1a; 解決 GPG 密鑰驗證失敗的問題下載 MySQL 官方 GPG 密鑰 使用以下命令下載并安裝 MySQL 的官方 GPG 密鑰&#xff1a; w…

大數據量返回方案(非分頁)

一、普通方式返回100萬條數據RestController RequestMapping("/bad") public class BadController {Autowiredprivate UserRepository userRepository;/*** 危險&#xff01;一次性加載 100 萬條到內存*/GetMapping("/all-users")public List<User> …

基于Casbin的微服務細粒度權限控制方案對比與實踐

基于Casbin的微服務細粒度權限控制方案對比與實踐 隨著微服務架構在互聯網和企業級應用中的廣泛應用&#xff0c;服務間的安全邊界愈發重要。傳統的集中式權限控制方式已難以滿足微服務的高并發、動態擴展和多語言支持等需求。本文將從主流的三種微服務權限控制方案入手&#x…

5G毫米波現狀概述(截止2025 年7月)

5G毫米波現狀概述(截止2025 年7月&#xff09; 原創 modem協議筆記 2025年07月25日 06:01 廣東 聽全文 當你在體育館看球賽時&#xff0c;想發段實時視頻到朋友圈卻總卡成PPT&#xff1b;當郊區的父母抱怨“光纖拉不到家&#xff0c;網速比蝸牛慢”—這些場景背后&#xff…

thymeleaf 日期格式化顯示

在Thymeleaf中處理日期格式化顯示主要有以下幾種方式&#xff1a; 1. 使用#dates.format()方法進行基礎格式化&#xff1a; <p th:text"${#dates.format(dateObj, yyyy-MM-dd HH:mm:ss)}"></p>這種方法支持自定義格式模式&#xff0c;如yyyy表示年份、MM…

【經驗分享】如何在Vscode的Jupyter Notebook中設置默認顯示行號

【經驗分享】如何在Vscode的Jupyter Notebook中設置默認顯示行號 打開設置&#xff0c;搜索&#xff1a;Notebook: Line Number&#xff0c;然后把這個設置為on

藍橋杯STL stack

STL stack 概述棧&#xff08;stack&#xff09;是一種遵循**后進先出&#xff08;LIFO&#xff09;**原則的線性數據結構&#xff0c;僅允許在棧頂進行插入和刪除操作。STL&#xff08;Standard Template Library&#xff09;中的 stack 是一個容器適配器&#xff0c;基于其他…

從0到1:飛算JavaAI如何用AI魔法重構MCP服務全生命周期?

摘要 本文詳細介紹了如何利用飛算JavaAI技術實現MCP&#xff08;Model Context Protocol&#xff09;服務的創建及通過的全過程。首先闡述了飛算JavaAI的基本概念、特點和優勢&#xff0c;接著對MCP服務的需求進行分析&#xff0c;然后按照軟件開發流程&#xff0c;從系統設計、…

Webpack Loader 完全指南:從原理到配置的深度解析

掌握 Webpack Loader 的核心機制&#xff0c;解鎖前端工程化進階技能前言&#xff1a;為什么需要理解 Loader&#xff1f; 在現代前端工程化體系中&#xff0c;Webpack 已成為構建工具的事實標準。然而面對非標準 JavaScript 文件或自定義語法時&#xff0c;你是否遇到過 Modul…

讀書筆記:《我看見的世界》

《我看見的世界.李飛飛自傳》李飛飛 著&#xff0c;趙燦 譯個人理解&#xff1a; 是本自傳&#xff0c;也是AI的發展史 堅持&#xff0c;總會轉機&#xff0c;“一不小心”也許就成了算法、大規模數據、原始算力人工智能似乎一夜之間從一個小眾的學術領域爆發成為推動全球變革的…

使用純NumPy實現回歸任務:深入理解機器學習本質

在深度學習框架普及的今天&#xff0c;回歸基礎用NumPy從頭實現機器學習模型具有特殊意義。本文將完整演示如何用純NumPy實現二次函數回歸任務&#xff0c;揭示機器學習底層原理。整個過程不使用任何深度學習框架&#xff0c;每一行代碼都透明可見。1. 環境配置與數據生成 impo…

java理解

springboot 打包 mvn install:install-file -Dfile=<path-to-jar> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=jar <path-to-jar> 是你的 JAR 文件的路徑。 <group-id> 是你的項目的組 ID。 <…

圖論核心算法詳解:從存儲結構到最短路徑(附C++實現)

目錄 一、圖的基礎概念與術語 二、圖的存儲結構 1. 鄰接矩陣 實現思路&#xff1a; 2. 鄰接表 實現思路&#xff1a; 應用場景&#xff1a; 時間復雜度分析&#xff1a; 三、圖的遍歷算法 1. 廣度優先搜索&#xff08;BFS&#xff09; 核心思想&#xff1a; 應用場…