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

Spring Boot 一個(gè)注解搞定加密 + 解密 + 簽名 + 驗(yàn)簽(一文全解)

 更新時(shí)間:2025年09月20日 09:49:35   作者:半部論語  
本文介紹了一種基于Spring Boot 3.x的接口安全解決方案,通過自定義注解@ApiSecurity結(jié)合AOP切面,實(shí)現(xiàn)請(qǐng)求解密、驗(yàn)簽、響應(yīng)加密及加簽的自動(dòng)化處理,_springboot api aop 報(bào)文加解密

Spring Boot 一個(gè)注解搞定「加密 + 解密 + 簽名 + 驗(yàn)簽」

本文基于 Spring Boot 3.x,通過一個(gè)自定義注解 + AOP,一行注解即可給任何 Controller 方法加上
請(qǐng)求解密 → 驗(yàn)簽 → 響應(yīng)加密 → 加簽 的完整鏈路,并可直接拷貝到生產(chǎn)環(huán)境使用。

一、最終效果

@PostMapping("/order")
@ApiSecurity(decryptRequest = true, encryptResponse = true)   // ← 就這么一行
public OrderResp createOrder(@RequestBody OrderReq req) {
    return service.create(req);
}
  • 請(qǐng)求體:RSA 加密后的 AES 密鑰 + AES 加密后的業(yè)務(wù) JSON + 簽名
  • 框架自動(dòng)完成 解密 → 驗(yàn)簽 → 業(yè)務(wù)處理 → 響應(yīng)加密 → 加簽
  • 零侵入,老接口想加安全,貼一個(gè)注解即可。

二、傳輸對(duì)象

@Data
public class ApiSecurityParam {
    private String appId;      // 應(yīng)用標(biāo)識(shí)
    private String key;        // RSA 加密后的 AES 密鑰(Base64)
    private String data;       // AES 加密的業(yè)務(wù) 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; // 請(qǐng)求體是否解密
    boolean encryptResponse() default false; // 響應(yīng)體是否加密
    boolean sign()            default true;  // 是否驗(yàn)簽/加簽
}

四、AOP 切面(RequestBodyAdvice + ResponseBodyAdvice)

同時(shí)解決 InputStream 只能讀一次 的問題。

4.1 解密 & 驗(yàn)簽 RequestBodyAdvice

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DecryptRequestAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(ApiSecurity.class)
                && methodParameter.getMethodAnnotation(ApiSecurity.class).decryptRequest();
    }
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage,
                                  MethodParameter parameter, Type targetType,
                                  Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }
    @SneakyThrows
    @Override
    public 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. 防重放校驗(yàn)(timestamp、nonce)
        checkReplay(param);
        // 2. RSA 私鑰解密 AES 密鑰
        String aesKey = RSAUtil.decryptByPrivateKey(param.getKey(), RsaKeyHolder.PRIVATE_KEY);
        // 3. AES 解密業(yè)務(wù) JSON
        String json = AESUtil.decrypt(param.getData(), aesKey);
        // 4. 驗(yàn)簽
        boolean ok = RSAUtil.verify(json + param.getTimestamp() + param.getNonce(),
                                    RsaKeyHolder.PUBLIC_KEY, param.getSign());
        if (!ok) throw new BizException("驗(yàn)簽失敗");
        return new MappingJacksonInputMessage(new ByteArrayInputStream(json.getBytes()),
                                              inputMessage.getHeaders());
    }
}

4.2 加密 & 加簽 ResponseBodyAdvice

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        ApiSecurity anno = returnType.getMethodAnnotation(ApiSecurity.class);
        return anno != null && anno.encryptResponse();
    }
    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        String json = JSON.toJSONString(body);
        // 1. 隨機(jī) AES 密鑰
        String aesKey = AESUtil.randomKey(128);
        // 2. AES 加密響應(yīng)
        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 讀取公私鑰

六、性能 & 安全小貼士

點(diǎn)建議
對(duì)稱加密AES-128-CBC/PKCS5Padding
非對(duì)稱RSA-2048
防重放timestamp ±5 min + nonce 一次性
密鑰輪換每日定時(shí)任務(wù)刷新 RSA 密鑰對(duì)
性能AES 每次隨機(jī) IV,RSA 只加密 128bit 密鑰,無壓力

七、小結(jié)

通過以上 一個(gè)注解 + 兩個(gè) Advice,在 Spring Boot 中實(shí)現(xiàn) 企業(yè)級(jí)安全傳輸

  • 0 侵入:老接口貼注解即可
  • 高可擴(kuò)展:支持 GET/POST、Header 傳參、自定義算法
  • 已落地:可直接封裝為 spring-boot-starter-security-api,全公司復(fù)用。

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

到此這篇關(guān)于Spring Boot 一個(gè)注解搞定「加密 + 解密 + 簽名 + 驗(yàn)簽」的文章就介紹到這了,更多相關(guān)Spring Boot注解加密 解密 簽名 驗(yàn)簽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java輸出通過InetAddress獲得的IP地址數(shù)組詳細(xì)解析

    Java輸出通過InetAddress獲得的IP地址數(shù)組詳細(xì)解析

    由于byte被認(rèn)為是unsigned byte,所以最高位的1將會(huì)被解釋為符號(hào)位,另外Java中存儲(chǔ)是按照補(bǔ)碼存儲(chǔ),所以1000 0111會(huì)被認(rèn)為是補(bǔ)碼形式,轉(zhuǎn)換成原碼便是1111 0001,轉(zhuǎn)換成十進(jìn)制數(shù)便是-121
    2013-09-09
  • jstl之map,list訪問遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)

    jstl之map,list訪問遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)

    下面小編就為大家?guī)硪黄猨stl之map,list訪問遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases

    Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases

    這篇文章主要介紹了Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java中的CAS和自旋鎖詳解

    Java中的CAS和自旋鎖詳解

    這篇文章主要介紹了Java中的CAS和自旋鎖詳解,CAS算法(Compare And Swap),即比較并替換,是一種實(shí)現(xiàn)并發(fā)編程時(shí)常用到的算法,Java并發(fā)包中的很多類都使用了CAS算法,需要的朋友可以參考下
    2023-10-10
  • 將idea中xml文件背景顏色去除的圖文教程

    將idea中xml文件背景顏色去除的圖文教程

    這篇文章主要介紹了將idea中xml文件背景顏色去除,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 淺析如何在IDEA中高效使用Test注解進(jìn)行單元測(cè)試

    淺析如何在IDEA中高效使用Test注解進(jìn)行單元測(cè)試

    在軟件開發(fā)過程中,單元測(cè)試是保證代碼質(zhì)量的重要手段之一,那么如何在IDEA中高效使用Test注解進(jìn)行單元測(cè)試呢,下面小編就來和大家簡單講講
    2025-04-04
  • Java基于遞歸解決全排列問題算法示例

    Java基于遞歸解決全排列問題算法示例

    這篇文章主要介紹了Java基于遞歸解決全排列問題算法,結(jié)合實(shí)例形式分析了Java使用遞歸算法解決全排列問題的原理與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-11-11
  • Java 全方位講解面向?qū)ο筇攸c(diǎn)與使用

    Java 全方位講解面向?qū)ο筇攸c(diǎn)與使用

    面向?qū)ο箝_發(fā)方法將面向?qū)ο蟮乃枷霊?yīng)用于軟件開發(fā)過程中,指導(dǎo)開發(fā)活動(dòng),是建立在“對(duì)象”概念基礎(chǔ)上的方法學(xué),簡稱OO( Object-Oriented)方法
    2022-04-04
  • Java并發(fā)編程之線程安全性

    Java并發(fā)編程之線程安全性

    這篇文章主要介紹了Java并發(fā)編程之線程安全性,文章基于Java的相關(guān)內(nèi)容詳細(xì)的展開詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-04-04
  • 配置Ant執(zhí)行Jmeter腳本過程詳解

    配置Ant執(zhí)行Jmeter腳本過程詳解

    這篇文章主要介紹了配置Ant執(zhí)行Jmeter腳本過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論

高密市| 抚松县| 延安市| 左权县| 延津县| 金塔县| 舒城县| 高密市| 潜山县| 四会市| 孝义市| 宁晋县| 罗山县| 自治县| 江川县| 陵川县| 海兴县| 蛟河市| 桃园市| 民乐县| 昆明市| 额尔古纳市| 辽源市| 青浦区| 延安市| 同仁县| 三明市| 满洲里市| 尉犁县| 南宫市| 中超| 大余县| 郎溪县| 张家口市| 新竹县| 新巴尔虎左旗| 吴旗县| 济源市| 怀宁县| 望谟县| 江阴市|