API 驗證機制怎麼設計?從金流串接學到的三層防護實戰

教學指南

AI 文章延伸

AI 幫你讀這篇文章

選擇平台後可直接帶入閱讀脈絡,快速整理重點、補齊盲點,並延伸到同站相關文章。

我們最近在做一個專案,兩個網站之間需要透過 REST API 互相溝通——A 站負責下指令,B 站負責執行。兩邊各自獨立部署,靠 API 串起來。

問題來了:API 端點是公開的。只要有人知道網址格式,就能嘗試呼叫。如果驗證機制不夠嚴謹,別人拿到 API Key 就能對你的網站做任何事——讀取資料、修改設定、觸發操作。

這篇分享我們怎麼設計這套 API 驗證機制,以及背後的思考脈絡。

只有 API Key 不夠嗎?

最直覺的做法是發一組 API Key,每次請求帶上這組 Key,後端驗證通過就放行。很多服務都這樣做,簡單有效。

但光靠 API Key 有幾個風險:

  • Key 外洩就全完了。 一旦 Key 被截取,攻擊者可以無限次使用,直到你發現並撤銷。
  • 中間人攻擊。 如果有人在傳輸過程中攔截到請求,他拿到的不只是 Key,還有完整的請求內容,可以原封不動地重送。
  • 重送攻擊(Replay Attack)。 即使用了 HTTPS,攻擊者如果在任何環節拿到一個合法請求的副本,就能反覆重送這個請求來執行操作。

我們需要的是:即使有人拿到了 API Key,甚至截取了一個完整的合法請求,他也沒辦法拿這些東西來搞事。

從 WooCommerce 金流學到的做法

這個設計其實不是我們原創。靈感來自之前串接 WooCommerce 金流的經驗。

做過金流串接的人應該都知道,不管是綠界、藍新還是其他台灣的金流服務商,他們在處理付款通知(通常叫 callback 或 webhook)時,都不會只用一組 API Key 來驗證。他們的做法通常是:把請求裡的關鍵欄位串在一起,加上一組只有雙方知道的密鑰,算出一個雜湊值(Hash),然後把這個 Hash 附在請求裡一起送過來。

收到請求的那一方,用同樣的欄位、同樣的密鑰、同樣的算法重新算一次。兩邊的 Hash 一致,才代表這個請求是真的。

這個機制叫做「請求簽章(Request Signature)」。金流業者用它來保護每一筆交易通知的真實性。我們把同樣的概念套用在兩個網站之間的 API 通訊上。

三層驗證設計

最後我們設計了三層驗證,每一層解決不同的問題。

第一層:API Key

這是基本的身份識別。A 站和 B 站之間透過一組 Key 配對——管理員在 B 站產生一組 64 字元的隨機金鑰,複製貼到 A 站完成配對。B 站只儲存 Key 的 Hash 值,不存明文。

這一層解決的是「你是誰」的問題。沒有 Key,連門都進不了。

第二層:SHA-256 簽章

光有 Key 不夠。每次請求,A 站會把三個東西串在一起:

目標網站網址 | API Key | 當前時間戳

然後用 SHA-256 算出一個 Hash,放在請求的 Header 裡送過來。

B 站收到請求後,用同樣的三個值重新算一次 Hash。兩邊結果一致,才代表這個請求沒有被竄改過,而且確實來自知道 Key 的那一方。

為什麼要把網站網址也加進去?因為同一組 Key 如果能用在不同網站上就麻煩了。把網址綁進簽章裡,就算有人拿到 Key,也只能對特定網站發請求。

第三層:時間戳驗證

簽章裡包含了時間戳,但我們還額外做了一件事:檢查這個時間戳是不是太舊了。

規則很簡單——時間戳和伺服器當前時間的差異超過 5 分鐘,直接拒絕。

這一層專門對付重送攻擊。假設有人截取了一個合法請求,他拿到的 Hash 裡面包含了當時的時間戳。等他試圖重送這個請求的時候,時間戳已經過期了。他沒辦法修改時間戳,因為改了時間戳,Hash 就對不上。他也沒辦法重新算 Hash,因為他不知道 API Key。

5 分鐘的容許範圍是考慮到兩台伺服器之間可能有時間差,太短會誤判,太長又失去防護效果。金流服務商的做法也差不多是這個範圍。

實際的請求長什麼樣子

A 站呼叫 B 站 API 時,會帶三個自訂 Header:

  • API Key:用來做第一層身份驗證
  • Hash:用網站網址、Key、時間戳算出來的 SHA-256 簽章
  • Timestamp:發送請求的 Unix 時間戳

B 站收到請求後的驗證順序:

  1. 先看有沒有帶 API Key,沒有就直接擋掉
  2. 驗證 API Key 是否正確
  3. 檢查時間戳是否在 5 分鐘以內
  4. 用同樣的材料算一次 Hash,比對是否一致

四關都過了,才放行。任何一關失敗,都會回傳對應的錯誤碼,讓呼叫方知道是哪裡出了問題。

Key 的管理方式

安全機制設計完了,還有一個問題:管理員怎麼管理這組 Key?

我們的做法是在 B 站的後台加一個管理介面。管理員點「產生」,系統生成一組 Key,完整顯示一次。管理員複製下來貼到 A 站,之後這組 Key 就再也不會以明文出現了——後台只會顯示前 8 碼加後 4 碼的遮罩版本。

如果 Key 外洩了,管理員可以「重新產生」,舊的 Key 立刻失效,A 站需要重新配對。也可以直接「撤銷」,切斷所有 API 連線。

這個設計參考了 GitHub Personal Access Token 的做法——產生時看一次,之後只能看到局部。原因很實際:如果後台隨時能看到完整 Key,那任何能進後台的人都能拿到 Key。只顯示一次,能降低 Key 被二次外洩的風險。

這個設計不是萬無一失

幾個我們知道的限制:

依賴 HTTPS。 簽章機制保護的是請求的真實性和時效性,不是機密性。如果不用 HTTPS,所有 Header 都是明文傳輸,簽章的意義就大打折扣。不過現在幾乎所有正式環境都有 SSL 了,這個前提條件算合理。

時間同步。 兩台伺服器的時間如果差太多,合法請求也會被拒絕。5 分鐘的容許範圍在大部分情境下夠用,但如果遇到時間嚴重漂移的伺服器,可能需要排查。

Key 管理靠人。 系統能做的是產生夠強的隨機 Key、安全儲存、提供撤銷機制。但管理員把 Key 貼在 Slack 公開頻道或存在記事本裡,系統也管不了。

回頭看這個設計

整個驗證機制其實沒有用到什麼高深的技術。SHA-256 是標準的雜湊算法,時間戳驗證是基本的防重送手段,API Key 更是最常見的身份識別方式。真正的關鍵是把這三層組合在一起,讓每一層各自負責不同的安全面向。

金流業者用這套做法保護每一筆交易通知,已經經過多年的實戰驗證。我們只是把同樣的邏輯搬到兩個網站之間的 API 通訊上。根據我們的經驗,這個組合在「安全性」和「實作複雜度」之間取得了不錯的平衡——不需要導入 OAuth 或 JWT 這類重量級框架,用幾個簡單的元件就能達到足夠的防護等級。

如果你也在做類似的雙站 API 通訊,不妨參考金流串接的驗證模式。那些被大量交易驗證過的設計,通常比自己從頭發明的方案更可靠。

Google 偏好來源

把我們設為 Google 偏好來源

喜歡我們的內容嗎?一鍵將我們設為偏好來源,未來在 Google 焦點新聞與 AI 概覽中就能優先看到我們的文章。

作品案例

看看我們打造的產品與專案。從 WordPress 外掛到 AI 客服方案,每一個作品都是實戰經驗的累積。

瀏覽作品案例

服務項目

WordPress 開發、WooCommerce 電商、LINE 整合、AI 解決方案,依據你的需求提供最適合的技術服務。

瀏覽服務項目

Contact

聯絡我們

有任何技術需求、專案諮詢或合作想法,歡迎填寫以下表單或聯繫LINE官方帳號,我們會盡快回覆。

諮詢類型 必須