當前位置: 妍妍網 > 碼農

SpringBoot 快速實作 api 加密!so easy~

2024-04-02碼農

在計畫中,為了保證數據的安全,我們常常會對傳遞的數據進行加密。常用的加密演算法包括對稱加密(AES)和非對稱加密(RSA),博主選取碼雲上最簡單的API加密計畫進行下面的講解。

https://gitee.com/isuperag/rsa-encrypt-body-spring-boot

計畫介紹

該計畫使用RSA加密方式對API介面返回的數據加密,讓API數據更加安全。別人無法對提供的數據進行破解。Spring Boot介面加密,可以對返回值、參數值透過註解的方式自動加解密 。

什麽是RSA加密

首先我們當然是了解RSA加密

RSA加密是一種非對稱加密。可以在不直接傳遞金鑰的情況下,完成解密。這能夠確保資訊的安全性,避免了直接傳遞金鑰所造成的被破解的風險。是由一對金鑰來進行加解密的過程,分別稱為公鑰和私鑰。兩者之間有數學相關,該加密演算法的原理就是對一極大整數做因數分解的困難性來保證安全性。通常個人保存私鑰,公鑰是公開的(可能同時多人持有)。

舉例子大法

加密和簽名都是為了安全性考慮,但略有不同。常有人問加密和簽名是用私鑰還是公鑰?其實都是對加密和簽名的作用有所混淆。簡單的說,加密是為了防止資訊被泄露,而簽名是為了防止資訊被篡改。這裏舉2個例子說明。

「第一個場景:」 戰場上,B要給A傳遞一條訊息,內容為某一指令。

RSA的加密過程如下:

  • A生成一對金鑰(公鑰和私鑰),私鑰不公開,A自己保留。公鑰為公開的,任何人可以獲取。

  • A傳遞自己的公鑰給B,B用A的公鑰對訊息進行加密。

  • A接收到B加密的訊息,利用A自己的私鑰對訊息進行解密。

  • 在這個過程中,只有2次傳遞過程,第一次是A傳遞公鑰給B,第二次是B傳遞加密訊息給A,即使都被敵方截獲,也沒有危險性,因為只有A的私鑰才能對訊息進行解密,防止了訊息內容的泄露。

    「第二個場景:」 A收到B發的訊息後,需要進行回復「收到」。

    RSA簽名的過程如下:

  • A生成一對金鑰(公鑰和私鑰),私鑰不公開,A自己保留。公鑰為公開的,任何人可以獲取。

  • A用自己的私鑰對訊息加簽,形成簽名,並將加簽的訊息和訊息本身一起傳遞給B。

  • B收到訊息後,在獲取A的公鑰進行驗簽,如果驗簽出來的內容與訊息本身一致,證明訊息是A回復的。

  • 在這個過程中,只有2次傳遞過程,第一次是A傳遞加簽的訊息和訊息本身給B,第二次是B獲取A的公鑰,即使都被敵方截獲,也沒有危險性,因為只有A的私鑰才能對訊息進行簽名,即使知道了訊息內容,也無法偽造帶簽名的回復給B,防止了訊息內容的篡改。

    但是,綜合兩個場景你會發現,第一個場景雖然被截獲的訊息沒有泄露,但是可以利用截獲的公鑰,將假指令進行加密,然後傳遞給A。第二個場景雖然截獲的訊息不能被篡改,但是訊息的內容可以利用公鑰驗簽來獲得,並不能防止泄露。所以在實際套用中,要根據情況使用,也可以同時使用加密和簽名,比如A和B都有一套自己的公鑰和私鑰,當A要給B發送訊息時,先用B的公鑰對訊息加密,再對加密的訊息使用A的私鑰加簽名,達到既不泄露也不被篡改,更能保證訊息的安全性。

    加密實戰

    博主你嗶哩嗶哩這麽多,我已經知道了RSA是幹什麽了。不就是 公鑰加密、私鑰解密、私鑰簽名、公鑰驗簽

    實戰準備

    1、新建一個springboot計畫

    springboot_api_encryption

    2、引入maven依來

    <dependency>
    <groupId>cn.shuibo</groupId>
    <artifactId>rsa-encrypt-body-spring-boot</artifactId>
    <version>1.0.1.RELEASE</version>
    </dependency>

    3、啟動類Application中添加@EnableSecurity註解

    @SpringBootApplication
    @EnableSecurity
    public classDemoApplication{
    publicstaticvoidmain(String[] args){
    SpringApplication.run(DemoApplication. classargs);
    }
    }

    4、在application.yml或者application.properties中添加RSA公鑰及私鑰

    公鑰私鑰的生成文章後面會放出生成工具

    rsa:
    encrypt:
    open: false# 是否開啟加密 true or false
    showLog: true# 是否打印加解密log true or false
    publicKey: # RSA公鑰 軟體生成
    privateKey: # RSA私鑰 軟體生成

    5、對Controller 裏面的API方法進行加密

    @Encrypt
    @GetMapping("/encryption")
    public TestBean encryption(){
    TestBean testBean = new TestBean();
    testBean.setName("shuibo.cn");
    testBean.setAge(18);
    return testBean;
    }

    6、對傳過來的加密參數解密

    其他java端程式可以用註解,如果是vue,請用RSA金鑰解密

    @Decrypt
    @PostMapping("/decryption")
    public String Decryption(@RequestBody TestBean testBean){
    return testBean.toString();
    }

    真刀真槍

    1、引入maven

    2、啟動類添加註解

    3、YML添加配置金鑰

    4、建立一個實體類

    5、寫一個對外API介面

    6、啟動計畫

    請求地址: http://localhost:8080/encryption

    我們看到返回的數據未加密

    7、修改

    修改open為true 開啟加密

    rsa:
    encrypt:
    open: true# 是否開啟加密 true or false
    showLog: true# 是否打印加解密log true or false
    publicKey: # RSA公鑰 軟體生成
    privateKey: # RSA私鑰 軟體生成

    8、再次重新開機計畫

    請求地址: http://localhost:8080/encryption

    我們看到返回的數據已加密

    9、加密日誌

    解密實戰

    如果是其他springboot計畫,跟前面一樣。我們這兒就當客戶端是springboot計畫,其他的請使用RSA解密協定解密!

    伺服端有私金鑰、公金鑰

    前端只需要公金鑰就可以

    實戰準備

    在原來的springboot基礎上寫一份解密方法

    1、前端js解密方法

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.0.0-rc.1/jsencrypt.js"></script>

    2、後台增加解密方法

    /**
     * 解密
     * @param user
     * @return
     */

    @PostMapping("/decryption")
    @Decrypt
    @ResponseBody
    public String Decryption(@RequestBody User user){
    System.out.println(user.toString());
    return user.toString();
    }

    3、js方法

    #公鑰
    var PUBLIC_KEY = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAobhGH4WMwMvJRUlTxWrCVIOQtsHijAxPJNvAWAgq80ADpFEWrpbcGB9cKqp6XHRH4k/CVtCUZ7jm9UKwhaeAm18sKtcwe+M8JFNX6FSHpgde0o8C9S/QpcmLxf4iN7nGZ7P3ZTvMdmKUcdRMsVQnsydG2Bj6gRxP2+kexEebTeODbdM7dHlkxAL0RxGWmX/ZOBzsoWZw2gKcC0vxwyIZBGHUdImG2T3nEA+VMfK2Yqv3uSYukmlKP+0mjfhrTtLFDuTV1VER9BfryBMvpQCxLO4pqgZnXPd+SOQcZHZ2OL0wqo5OX1+GPYx7TNxz5Qi76pK//T2mH7s6X/BuyT21HQIDAQAB';
    /**
     * 加密方法
     * @returns {PromiseLike<ArrayBuffer>}
     * @constructor
     */

    functionRSA_encryption(jsonData{
    var encrypt = new JSEncrypt();
     encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
    var encrypted = encrypt.encrypt(JSON.stringify(jsonData));
    console.log('加密前數據:%o', str);
    console.log('加密後數據:%o', encrypted);
    return encrypted;
    }

    /**
     * 送出方法
     */

    functiontijiao() {
    var str = {
    "name":"1223334",
    "password":"asd",
    age:1
     };
    $.ajax({
    url"/decryption",
    type : "POST",
    contentType"application/json;charset=utf-8",
    data : RSA_encryption(str) ,
    success : function(data{
    alert(data);
    }
    })
    }

    真刀真槍

    1、 Controller添加解密方法介面

    2、前端頁面引入js以及方法

    <!DOCTYPE html>
    <htmllang="en">
    <head>
    <metacharset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    加密傳後端,後端解密
    <buttonid="jiami"onclick="tijiao()">加密傳後端</button>
    <scriptsrc="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <scriptsrc="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.0.0-rc.1/jsencrypt.js"></script>
    <script>
    var PUBLIC_KEY = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAobhGH4WMwMvJRUlTxWrCVIOQtsHijAxPJNvAWAgq80ADpFEWrpbcGB9cKqp6XHRH4k/CVtCUZ7jm9UKwhaeAm18sKtcwe+M8JFNX6FSHpgde0o8C9S/QpcmLxf4iN7nGZ7P3ZTvMdmKUcdRMsVQnsydG2Bj6gRxP2+kexEebTeODbdM7dHlkxAL0RxGWmX/ZOBzsoWZw2gKcC0vxwyIZBGHUdImG2T3nEA+VMfK2Yqv3uSYukmlKP+0mjfhrTtLFDuTV1VER9BfryBMvpQCxLO4pqgZnXPd+SOQcZHZ2OL0wqo5OX1+GPYx7TNxz5Qi76pK//T2mH7s6X/BuyT21HQIDAQAB';
    /**
    * 加密方法
    * @returns {PromiseLike<ArrayBuffer>}
    * @constructor
    */

    functionRSA_encryption(jsonData{
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
    var encrypted = encrypt.encrypt(JSON.stringify(jsonData));
    console.log('加密前數據:%o', jsonData);
    console.log('加密後數據:%o', encrypted);
    return encrypted;
    }
    /**
    * 送出方法
    */

    functiontijiao() {
    var str = {
    "name":"1223334",
    "password":"asd",
    age:1
    };
    $.ajax({
    url"/decryption",
    type : "POST",
    contentType"application/json;charset=utf-8",
    data : RSA_encryption(str) ,
    success : function(data{
    alert(data);
    }
    })
    }
    </script>
    </body>
    </html>

    3、啟動存取

    http://localhost:8080

    4、後台解密日誌

    總結

    經過上面的介面加密解密操作。可以看出我們的介面如果沒有公鑰、或者私鑰別人根本無法解密!這樣就對API介面起到了很好的保護作用,防止別人抓包!

    祝大家:每天學習一點,技術成長飛快

    計畫坑點

    此計畫的demo無法存取,難點就在前端如何加密回傳到後台解密,此坑我帶大家爬出來了!

    以下是主意事項:

    1、主意ajax的 contentType: 「application/json;charset=utf-8」

    $.ajax({
    url: "/decryption",
    type : "POST",
    contentType: "application/json;charset=utf-8",
    data : RSA_encryption(str) ,
    success : function(data) {
    alert(data);
    }
    })

    2、解密方法必須 @RequestBody

    @PostMapping("/decryption")
    @Decrypt
    @ResponseBody
    public String Decryption(@RequestBody User user){
    System.out.println(user.toString());
    return user.toString();
    }

    >>

    END

    精品資料,超贊福利,免費領

    微信掃碼/長按辨識 添加【技術交流群

    群內每天分享精品學習資料

    最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎並行JVMMySQLRedisSpringSpringMVCSpringBootSpringCloud訊息佇列等多個型別),歡迎您的使用。

    👇👇

    👇點選"閱讀原文",獲取更多資料(持續更新中