具代表性的面試主題

後端面試:如何用 HTTP Message Signatures 保護 API 完整性?

後端困難
OfferCC 編輯團隊發佈 更新

題幹

一個支付合作方要求驗證每個 HTTP 請求的傳送方和內容完整性。請基於 RFC 9421 設計簽名與驗簽流程,並說明覆蓋哪些元件、如何防重放、輪換金鑰以及處理代理改寫。

題幹與適用場景

一個支付合作方要求驗證每個 HTTP 請求的傳送方和內容完整性。請基於 RFC 9421 設計簽名與驗簽流程,並說明覆蓋哪些元件、如何防重放、輪換金鑰以及處理代理改寫。

RFC 9421 將簽名輸入、覆蓋的 HTTP 元件和 created、expires、nonce 等參數分開定義。題目考察能否把「誰簽的」和「哪些位元組被簽」落實為可互通協定,而不是只說「給 body 做 SHA-256」。

面試官考察點

重點包括:覆蓋元件是否足以綁定請求語意;客戶端和伺服器如何規範化簽名基線;時間、nonce 和金鑰 ID 如何防重放;代理、重試、壓縮和多租戶如何影響驗簽;以及金鑰發布、撤銷和監控是否可維運。

30 秒回答框架

「我先定義協定要求覆蓋的方法、目標路徑、authority、關鍵業務標頭和 Content-Digest,並固定簽名演算法、參數順序和時鐘容差。伺服器先解析 Signature-Input,按相同規則重建簽名基線,再查金鑰、驗證簽名、檢查 created、expires 和一次性 nonce,最後才進入業務。金鑰用版本化 key ID 支援雙寫驗簽和撤銷;代理只能改寫未覆蓋欄位,否則驗簽失敗。」

分步驟深入解答

第一步:明確要證明的屬性

簽名可證明持鑰方對特定 HTTP 元件簽過名,也能偵測傳輸中的改寫;它不取代 TLS、授權、輸入校驗或業務冪等。先寫清楚需要認證、完整性,還是不可否認性。

第二步:選擇覆蓋元件

至少覆蓋方法、目標路徑和 authority;依業務再覆蓋 content-digest、冪等鍵、租戶 ID 或關鍵業務標頭。不要只簽一個可被替換的欄位,也不要盲目覆蓋會被合法代理重寫的標頭。元件清單必須成為版本化協定。

第三步:規範化簽名基線

客戶端和伺服器必須使用 RFC 9421 規定的元件識別、順序、參數編碼和衍生元件規則。伺服器不能直接拼接原始 Header 字串猜測結果;應從解析後的請求和 Signature-Input 重建同一基線,並拒絕未知或重複的關鍵元件。

第四步:保護請求內容

有 body 的請求先產生 Content-Digest,再把該欄位納入簽名。驗簽前按收到的位元組計算摘要,確保壓縮、轉碼或 JSON 重排不會靜默改變內容。若代理會解壓或重編碼,協定必須明確簽名發生在修改前還是修改後。

第五步:設計時間與防重放

要求 created,必要時要求 expires 和唯一 nonce。伺服器校驗時間窗口和時鐘偏差,並在租戶範圍短期記錄已用 nonce;重試相同業務請求依賴冪等鍵,不是無限放寬簽名有效期。時間通過不代表業務請求可以重複執行。

第六步:實作金鑰發現與輪換

Signature-Input 帶有 key ID,伺服器從受控目錄或類 JWKS 發布端點讀取公鑰,並快取帶版本的結果。輪換時先發布新公鑰,再允許新舊 key 雙驗簽,確認舊流量耗盡後撤銷舊 key。私鑰只在簽名端使用,日誌不得記錄金鑰材料或完整簽名基線。

第七步:處理代理與重試邊界

明確哪些層可以新增追蹤標頭、重試請求或改變 authority。被覆蓋元件發生不被協定允許的改寫就應驗簽失敗;代理重試不能複製一次性 nonce,也不能把簽名轉發到不同目標。伺服器驗簽前不要執行寫入或昂貴業務邏輯。

第八步:觀測和故障處理

記錄 key ID、簽名版本、失敗類別、時鐘偏差、nonce 衝突、元件缺失和代理來源,使用請求 ID 關聯日誌。對合作方提供可操作錯誤碼,例如過期、未知 key、摘要不匹配;不要返回可幫助攻擊者試錯的詳細金鑰或基線內容。

設計取捨與邊界

非對稱簽名還是共享金鑰

非對稱金鑰便於多方驗簽和獨立撤銷,代價是簽名與金鑰基礎設施更複雜。共享 HMAC 成本較低,但驗證方也能偽造請求,適合雙方完全互信且邊界清晰的場景。

覆蓋範圍還是代理相容

覆蓋越多,完整性約束越強;覆蓋會被閘道合法修改的欄位則會造成誤失敗。把代理契約寫入協定,必要時由邊界代理重新簽名,而不是靜默放寬驗簽。

嚴格時間窗口還是離線重試

短窗口降低重放風險,卻要求時鐘同步和快速重試。離線客戶端應申請新的簽名,不應重用長期有效簽名;伺服器可按合作方設定受控容差。

失敗演練與演進計畫

代理修改路徑

在測試代理中改寫路徑或 authority,確認驗簽失敗且沒有進入業務;允許的追蹤標頭改寫不應影響簽名。

重放舊請求

重複傳送相同簽名和 nonce,驗證第二次被拒絕;使用新 nonce 但相同冪等鍵時,驗證業務層按冪等規則處理。

金鑰輪換窗口

同時發布新舊 key,驗證新舊簽名均能按策略通過;撤銷舊 key 後舊簽名應失敗,且不會因快取無限存活。

常見誤區與追問

誤區一:只簽 body 的雜湊

追問:攻擊者能否把簽名複製到另一個路徑或方法?應覆蓋目標元件並綁定請求語意。

誤區二:認為 HTTPS 已經足夠

追問:終止 TLS 的代理之後如何證明原始傳送方和內容沒有被內部層改寫?

誤區三:忽略 nonce 和時間

追問:捕獲的合法簽名能否在有效期內重複扣款?應結合時間窗口、nonce 和冪等鍵。

誤區四:輪換時立即刪除舊 key

追問:在途請求和多區域快取如何過渡?應先雙驗簽,再撤銷舊 key。

誤區五:把驗簽錯誤直接返回基線細節

追問:如何讓合作方排障又不洩露簽名輸入、金鑰或內部代理資訊?

延伸追問與參考答案

Content-Digest 為什麼還要放進簽名?

摘要證明 body 位元組,簽名把摘要與方法、目標和其他元件綁定,避免攻擊者把合法摘要搬到另一請求。

代理改寫後應該重新簽名嗎?

若改寫欄位屬於下游協定的一部分,邊界代理應以自己的身份重新簽名;否則應保持被覆蓋元件不變並讓原簽名繼續驗證。

如何區分認證和授權?

驗簽確認持鑰方簽過請求,授權仍需檢查租戶、帳戶、金額、冪等鍵和業務狀態,不能由簽名單獨決定是否執行。

公開來源

同類題目

資源

產品比較

每份比較均依官方資料整理,並標示複核日期。

查看完整比較