最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實現(xiàn)RSA+AES自動接口解密的實戰(zhàn)指南

 更新時間:2025年08月03日 11:26:34   作者:墨夶  
在當今數(shù)據(jù)泄露頻發(fā)的網(wǎng)絡環(huán)境中,接口安全已成為開發(fā)者不可忽視的核心議題,RSA+AES混合加密方案因其安全性高、性能優(yōu)越而被廣泛采用,本文將深入SpringBoot框架,手把手演示如何通過自定義注解+攔截器實現(xiàn)接口的自動化加解密,需要的朋友可以參考下

在當今數(shù)據(jù)泄露頻發(fā)的網(wǎng)絡環(huán)境中,接口安全已成為開發(fā)者不可忽視的核心議題。RSA+AES混合加密方案因其安全性高、性能優(yōu)越而被廣泛采用:

  • RSA(非對稱加密):解決密鑰分發(fā)難題,適合加密小數(shù)據(jù)(如AES密鑰)。
  • AES(對稱加密):高效加密大量數(shù)據(jù),適合傳輸業(yè)務參數(shù)。

本文將深入SpringBoot框架,手把手演示如何通過自定義注解+攔截器實現(xiàn)接口的自動化加解密,并提供完整工具類、AOP切片代碼及安全優(yōu)化策略。

一、項目依賴與環(huán)境準備

1.1 Maven依賴配置

pom.xml中添加必要的依賴:

<dependencies>
    <!-- SpringBoot Web支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- JSON處理工具 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.83</version>
    </dependency>

    <!-- 加密算法擴展(支持BCrypt等) -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>

    <!-- Lombok簡化代碼 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

1.2 密鑰生成與配置

RSA密鑰對生成

// 工具類:生成RSA密鑰對
public class KeyGenerator {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048); // 2048位密鑰長度
        KeyPair keyPair = keyGen.generateKeyPair();

        // 公鑰(客戶端使用)
        String publicKeyStr = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        System.out.println("Public Key:\n" + publicKeyStr);

        // 私鑰(服務端使用)
        String privateKeyStr = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        System.out.println("Private Key:\n" + privateKeyStr);
    }
}

配置文件中存儲密鑰

# application.yml
encrypt:
  rsa:
    public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
    private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC..."

二、加密工具類實現(xiàn)

2.1 RSA工具類

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtil {
    static {
        Security.addProvider(new BouncyCastleProvider()); // 添加BC支持
    }

    // 使用公鑰加密
    public static String encrypt(String data, String publicKeyStr) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(publicKeyStr);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
    }

    // 使用私鑰解密
    public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyStr);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(encryptedData)));
    }

    // 從Base64字符串生成公鑰
    private static PublicKey getPublicKeyFromBase64(String keyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }

    // 從Base64字符串生成私鑰
    private static PrivateKey getPrivateKeyFromBase64(String keyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(spec);
    }
}

2.2 AES工具類

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

public class AESUtil {
    // AES加密模式:CBC + PKCS7Padding
    private static final String AES_MODE = "AES/CBC/PKCS7Padding";
    private static final int IV_LENGTH = 16; // 初始化向量長度

    // 生成隨機AES密鑰
    public static String generateAESKey() throws Exception {
        byte[] key = new byte[16]; // 128位密鑰
        new SecureRandom().nextBytes(key);
        return Base64.getEncoder().encodeToString(key);
    }

    // AES加密
    public static String encrypt(String data, String aesKey) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(aesKey);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        byte[] iv = new byte[IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        Cipher cipher = Cipher.getInstance(AES_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

        // 將IV和密文合并返回
        byte[] result = new byte[iv.length + encryptedBytes.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(encryptedBytes, 0, result, iv.length, encryptedBytes.length);
        return Base64.getEncoder().encodeToString(result);
    }

    // AES解密
    public static String decrypt(String encryptedData, String aesKey) throws Exception {
        byte[] data = Base64.getDecoder().decode(encryptedData);
        byte[] iv = new byte[IV_LENGTH];
        byte[] encryptedBytes = new byte[data.length - IV_LENGTH];
        System.arraycopy(data, 0, iv, 0, IV_LENGTH);
        System.arraycopy(data, IV_LENGTH, encryptedBytes, 0, encryptedBytes.length);

        SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        Cipher cipher = Cipher.getInstance(AES_MODE);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return new String(cipher.doFinal(encryptedBytes), StandardCharsets.UTF_8);
    }
}

三、自定義注解與AOP切面

3.1 自定義解密注解 @RequestRSA

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestRSA {
    // 標記需要解密的接口
}

3.2 AOP切面實現(xiàn)自動解密

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * RSA+AES接口解密切面
 */
@Aspect
@Component
@Order(1)
public class RequestRSAAspect {

    @Value("${encrypt.rsa.private-key}")
    private String privateKey;

    /**
     * 攔截帶有@RequestRSA注解的方法
     */
    @Around("@annotation(requestRSA) || @within(requestRSA)")
    public Object decryptRequest(ProceedingJoinPoint joinPoint, RequestRSA requestRSA) throws Throwable {
        // 獲取請求體
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String body = getRequestBody(request);

        // 解析加密參數(shù)
        JSONObject encryptedJson = JSONObject.parseObject(body);
        String sym = encryptedJson.getString("sym"); // RSA加密的AES密鑰
        String asy = encryptedJson.getString("asy"); // AES加密的業(yè)務數(shù)據(jù)

        // RSA解密獲取AES密鑰
        String aesKey = RSAUtil.decrypt(sym, privateKey);

        // AES解密業(yè)務數(shù)據(jù)
        String decryptedData = AESUtil.decrypt(asy, aesKey);

        // 將解密后的數(shù)據(jù)注入方法參數(shù)
        Object[] args = injectDecryptedData(joinPoint, decryptedData);
        return joinPoint.proceed(args);
    }

    /**
     * 讀取請求體內(nèi)容
     */
    private String getRequestBody(HttpServletRequest request) throws Exception {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        return sb.toString();
    }

    /**
     * 將解密后的數(shù)據(jù)注入方法參數(shù)
     */
    private Object[] injectDecryptedData(ProceedingJoinPoint joinPoint, String decryptedData) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();

        for (int i = 0; i < parameters.length; i++) {
            if (parameters[i].isAnnotationPresent(RequestBody.class)) {
                // 將解密后的JSON字符串反序列化為目標對象
                args[i] = JSONObject.parseObject(decryptedData, parameters[i].getParameterizedType());
            }
        }
        return args;
    }
}

四、客戶端加密邏輯實現(xiàn)

4.1 客戶端加密流程

public class ClientEncryption {
    public static void main(String[] args) throws Exception {
        // 1. 隨機生成AES密鑰和IV
        String aesKey = AESUtil.generateAESKey();
        String aesIV = AESUtil.generateAESKey(); // 實際應使用SecureRandom生成IV

        // 2. 構(gòu)造請求參數(shù)
        JSONObject requestData = new JSONObject();
        requestData.put("username", "user123");
        requestData.put("password", "securePass");

        // 3. AES加密業(yè)務數(shù)據(jù)
        String asy = AESUtil.encrypt(requestData.toJSONString(), aesKey);

        // 4. 構(gòu)造AES密鑰信息
        JSONObject aesInfo = new JSONObject();
        aesInfo.put("key", aesKey);
        aesInfo.put("keyVI", aesIV);
        aesInfo.put("time", System.currentTimeMillis());

        // 5. RSA加密AES密鑰信息
        String sym = RSAUtil.encrypt(aesInfo.toJSONString(), "服務器公鑰");

        // 6. 構(gòu)造最終請求體
        JSONObject finalRequest = new JSONObject();
        finalRequest.put("sym", sym);
        finalRequest.put("asy", asy);

        System.out.println("加密后請求體:\n" + finalRequest.toJSONString());
    }
}

五、服務器端接口示例

5.1 帶解密注解的接口

@RestController
@RequestMapping("/api")
public class SecureController {

    @PostMapping("/login")
    @RequestRSA // 標記需要解密
    public Response login(@RequestBody LoginRequest request) {
        // 直接使用解密后的參數(shù)
        return new Response("登錄成功", request.getUsername());
    }
}

// 請求參數(shù)類
@Data
public class LoginRequest {
    private String username;
    private String password;
}

六、安全優(yōu)化與最佳實踐

6.1 密鑰管理策略

  • 私鑰存儲:使用配置中心(如Nacos)或密鑰管理服務(如AWS KMS)。
  • 公鑰分發(fā):通過HTTPS協(xié)議分發(fā),避免中間人攻擊。
  • 定期輪換:每30天更新一次RSA密鑰對。

6.2 時間戳防重放攻擊

在AOP切面中添加時間戳校驗:

private void validateTimestamp(JSONObject aesInfo) {
    long requestTime = aesInfo.getLong("time");
    long currentTime = System.currentTimeMillis();
    if (Math.abs(currentTime - requestTime) > 60000) { // 允許1分鐘內(nèi)
        throw new RuntimeException("請求超時,請重試");
    }
}

6.3 性能優(yōu)化建議

  • 緩存公鑰/私鑰對象:避免重復解析Base64字符串。
  • 異步解密:對高并發(fā)接口采用線程池異步處理。
  • 壓縮數(shù)據(jù):對加密后的數(shù)據(jù)進行GZIP壓縮減少傳輸體積。

七、完整調(diào)用流程圖解

客戶端流程:
[生成AES密鑰] → [AES加密數(shù)據(jù)] → [構(gòu)造AES信息] → [RSA加密AES信息] → [發(fā)送請求]

服務端流程:
[接收請求] → [AOP切面攔截] → [RSA解密AES密鑰] → [AES解密業(yè)務數(shù)據(jù)] → [注入?yún)?shù)執(zhí)行接口]

八、 構(gòu)建高安全接口的核心要點

模塊關(guān)鍵點注意事項
密鑰管理RSA公私鑰分離存儲,AES密鑰動態(tài)生成私鑰需加密存儲,定期輪換
加密流程RSA加密AES密鑰,AES加密業(yè)務數(shù)據(jù)確保IV隨機性,避免重復使用
AOP切面設計自動攔截、解密、參數(shù)注入處理異常情況(如密鑰錯誤、時間戳過期)
安全防護時間戳防重放、HTTPS傳輸、數(shù)據(jù)完整性校驗避免硬編碼密鑰,使用配置中心

九、 工具類與依賴說明

  • Bouncy Castle:提供擴展的加密算法支持(如PKCS7Padding)。
  • FastJSON:高效JSON序列化/反序列化。
  • Lombok:簡化POJO類的編寫(如@Data注解)。

以上就是SpringBoot實現(xiàn)RSA+AES自動接口解密的實戰(zhàn)指南的詳細內(nèi)容,更多關(guān)于SpringBoot RSA AES接口解密的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringCloud應用骨架開發(fā)詳解

    SpringCloud應用骨架開發(fā)詳解

    這篇文章主要介紹了SpringCloud應用骨架開發(fā)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Servlet的線程安全問題

    Servlet的線程安全問題

    本文主要介紹了Servlet的線程安全問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java實現(xiàn)向Word文檔添加文檔屬性

    Java實現(xiàn)向Word文檔添加文檔屬性

    這篇文章主要介紹了Java實現(xiàn)向Word文檔添加文檔屬性的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • SpringMVC框架中使用Filter實現(xiàn)請求日志打印方式

    SpringMVC框架中使用Filter實現(xiàn)請求日志打印方式

    這篇文章主要介紹了SpringMVC框架中使用Filter實現(xiàn)請求日志打印方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 淺談一下Java中的堆和棧

    淺談一下Java中的堆和棧

    這篇文章主要介紹了一下Java中的堆和棧,Java數(shù)據(jù)類型在執(zhí)行過程中存儲在兩種不同形式的內(nèi)存中:棧和堆,它們通常由運行Java虛擬機(JVM)的底層平臺維護,需要的朋友可以參考下
    2023-04-04
  • Double.parseDouble()與Double.valueOf()的區(qū)別及說明

    Double.parseDouble()與Double.valueOf()的區(qū)別及說明

    這篇文章主要介紹了Double.parseDouble()與Double.valueOf()的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • SpringBoot 統(tǒng)一異常處理詳解

    SpringBoot 統(tǒng)一異常處理詳解

    這篇文章主要介紹了SpringBoot統(tǒng)一異常處理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • MyBatis?typeHandler接口的定義和使用

    MyBatis?typeHandler接口的定義和使用

    TypeHandler被稱作類型處理器,MyBatis在設置預處理語句中的參數(shù)或從結(jié)果集中取出一個值時,都會用類型處理器將Java對象轉(zhuǎn)化為數(shù)據(jù)庫支持的類型或者將獲取到數(shù)據(jù)庫值以合適的方式轉(zhuǎn)換成Java類型,感興趣的同學可以參考下文
    2023-05-05
  • SpringCloud讓微服務實現(xiàn)指定程序調(diào)用

    SpringCloud讓微服務實現(xiàn)指定程序調(diào)用

    這篇文章主要介紹了SpringCloud讓微服務實現(xiàn)指定程序調(diào)用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • java使用Memcached簡單教程

    java使用Memcached簡單教程

    本文主要記錄Memcached的一些基本使用和簡單的Monitor,大家參考使用吧
    2013-12-12

最新評論

尉犁县| 内丘县| 洪江市| 湘潭县| 时尚| 宝鸡市| 新蔡县| 新兴县| 花莲县| 社旗县| 南和县| 张北县| 榆树市| 万年县| 南召县| 资溪县| 馆陶县| 岳普湖县| 正阳县| 长岭县| 普洱| 班戈县| 融水| 新沂市| 嫩江县| 台东市| 四会市| 虞城县| 平山县| 泗阳县| 富宁县| 岱山县| 长兴县| 新营市| 谢通门县| 会泽县| 丹阳市| 堆龙德庆县| 大足县| 建德市| 邓州市|