在項目裏寫接口的時候,我有時候會希望再多一層保護。
雖然 HTTPS 已經能保證傳輸安全,但它解決的更多是「傳輸過程中不被竊聽/篡改」的問題。
而我還想順帶做到幾點:
- 防止接口被隨便模擬調用
- 就算數據包被截獲,也看不懂內容
- 就算有人拿着同一份請求去重放,服務端也能拒絕
這些需求其實挺常見的,但並不複雜,説白了就是一套 RSA+AES 混合加密。
經典的思路
原理本身沒什麼新鮮的:
- 每次請求生成一個隨機 AES Key
- 用 AES 加密數據
- 再用 RSA 公鑰把 AES Key 加密後傳給後端
- 後端用 RSA 私鑰解密出 AES Key,再還原請求體
這是標準做法,網上能搜到很多講解。
真正麻煩的地方
難點其實不在原理,而是在項目裏真正用的時候。
比如要自己實現,就得寫:
- 每次生成隨機 AES Key
- RSA 公鑰加密 AES Key
- AES 加密/解密請求體
- 簽名計算、時間戳校驗,避免重放
- 各種異常處理(簽名錯、時間戳過期、解密失敗)
單看每一塊都不復雜,但組合在一起就有點煩。
而且這些邏輯和業務關係不大,卻不得不散落在代碼裏。
我做的小工具
為了省事,我乾脆把它們封裝成了前後端兩個庫:
- 前端是一個 npm 包
- 後端是一個 PHP 的 Composer 庫
目標就是:用起來跟普通請求沒什麼兩樣,但底層自動幫你做了加解密和校驗。
用法示例
前端:
npm install hejunjie-encrypted-request
import { encryptRequest } from "hejunjie-encrypted-request";
# 不建議在代碼裏寫死公鑰,建議通過讀取文件來獲取公鑰字符串
const encrypted = encryptRequest({ name: "張三" }, {
publicKey: "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
});
request.post("/api/user/info", encrypted)
.then(res => console.log(res));
後端:
composer require hejunjie/encrypted-request
use Hejunjie\EncryptedRequest\EncryptedRequestHandler;
// 自行在中間件或方法前完成請求參數的獲取
$param = $_POST;
// 同樣不建議代碼裏寫死私鑰
// 要麼私鑰作為 RSA_PRIVATE_KEY 放在.env裏(此方法就無需再傳遞$config)
// 要麼直接讀取文件作為配置傳遞
$config = [
'RSA_PRIVATE_KEY' => file_get_contents(private_key.pem)
];
$handler = new EncryptedRequestHandler($config);
$data = $encrypted->handle($param['en_data'] ?? '', $param['enc_payload'] ?? '', $param['timestamp'] ?? '', $param['sign'] ?? '');
print_r($data); // ['name' => '張三']
開發者只需要像平時一樣寫請求,庫會自動處理 AES/RSA 加解密、簽名、時間戳校驗、異常。
適合的場景
這個方案當然不是替代 HTTPS,而是作為額外的一層保護:
- 內部系統,不希望接口被隨便重放/模擬
- 中小項目,對安全有點額外要求,但不想上很重的安全框架
- 想快速把 RSA+AES 混合加密落地,而不用自己重複造輪子
倉庫地址
- 前端倉庫:npm-encrypted-request
- 後端倉庫:php-encrypted-request
希望能幫到和我一樣遇到類似需求的人。