系統設計面試:如何設計請求綁定的委託權限驗證層?
題目與適用場景
請設計一個委託權限驗證層:代理、工作負載或批次任務代表使用者或組織呼叫會花費資金、消耗計量資源、披露受監管資料或修改生產狀態的 HTTP API。系統需要在執行受保護請求前證明請求方擁有有界權限。題目參考 IETF HTTPAPI 的 2026 年 Internet-Draft;該文件仍是 work in progress,不能視為最終 RFC,也不等於支付協定。
面試官考察點
- 能否區分身份認證、委託授權、請求完整性與結算流程。
- 能否設計 401 挑戰、403 拒絕、nonce、過期時間與請求綁定。
- 能否處理重放、跨租戶混用、代理轉發、金鑰輪換與稽核。
- 能否在高風險動作前設定預算、策略與故障安全邊界。
回答前需要釐清的問題
- 受保護動作是匯出資料、寫入生產資源、呼叫下游,還是消費預算?
- 委託方、簽發方、執行請求方與驗證方分別由誰營運?
- 權限需要綁定 HTTP 方法、目標 URI、請求摘要,還是只綁定資源範圍?
- 允許離線驗證嗎?nonce 狀態可用性與時鐘偏差如何處理?
- 失敗時應拒絕請求、進入人工審批,還是降級為唯讀?
30 秒回答框架
把問題拆成四層:既有身份憑據證明「是誰」,委託證明說明「代表誰、能做什麼、上限多少」,請求綁定證明「只能用於哪一次請求」,驗證策略決定「現在是否允許」。沒有合格委託證明時回傳 401 challenge;證明存在但權限不足時回傳 403。證明應包含簽發者、請求方、主體、過期時間、nonce、目標方法與 URI、摘要及預算邊界。驗證成功後才執行動作,所有失敗路徑預設拒絕並保留稽核。
分步驟深入解答
1. 定義角色與信任邊界
主體是使用者、組織或服務;委託請求方是代理、裝置、任務或工作負載;簽發方代表主體簽發證明;驗證方位於受保護資源或閘道。OAuth Token Exchange 等系統可以負責取得證明,但驗證層只負責挑戰與呈現,不重複定義同意流程或帳戶綁定。
2. 設計挑戰與回應
沒有可接受證明時,驗證方回傳 401、WWW-Authenticate: Delegation 與 Cache-Control: no-store。證明語法有效但超過本地策略時回傳 403。錯誤體可用 Problem Details,但不能讓解釋欄位放寬挑戰約束。
HTTP/1.1 401 Unauthorized
Cache-Control: no-store
WWW-Authenticate: Delegation realm="api.example",
version=1, profile="budget", nonce="n-123", max-age=300挑戰中的 nonce、profile 與過期窗口應由驗證方控制,避免跨請求複製。
3. 綁定到將要執行的請求
證明至少綁定 HTTP 方法、可信 origin、目標 URI、請求內容摘要與有效期。代理重寫 Host 或路徑時,驗證方只使用受信任閘道設定重建 origin,不能採信未驗證的 X-Forwarded-*。方法大小寫、查詢參數順序與百分號編碼必須定義正規化規則。
{
"principal": "org-42",
"requester": "job-7",
"method": "POST",
"origin": "https://api.example",
"target_hash": "sha-256:...",
"nonce": "n-123",
"expires": "2026-08-04T05:00:00Z",
"limits": {"USD": 250}
}4. 驗證順序與故障安全
先解析版本與格式,再驗證簽章、簽發者信任、nonce 未重放、時間窗口、請求綁定與本地預算。任何依賴不可用、CBOR 非確定性、簽章失敗或 nonce 狀態遺失都拒絕請求,不能在驗證異常時自動放行。身份憑據與委託證明分層驗證,不能把一個有效證明當成另一個 API key 的授權。
5. 防止重放與跨租戶混用
nonce 儲存需要短 TTL、原子消費與租戶隔離;請求摘要與目標 origin 防止把同一證明複製到另一條 API。驗證方應拒絕已使用 nonce,限制時鐘偏差,並對預檢與最終請求使用一致的綁定欄位。高風險動作可以要求一次性證明與人工審批。
6. 預算與策略執行
預算只是一個權限 profile,不等於支付或結算。策略可以限制金額、服務單位、資料範圍、環境與下游呼叫次數。扣減應在動作提交的同一交易邊界內完成,或使用可補償的預留記錄,避免並發請求共同超過上限。
7. 金鑰、稽核與可運維性
簽發者發布可輪換的公鑰與版本;驗證方快取但必須支援撤銷與緊急金鑰切換。稽核記錄主體、請求方、目標、策略結果、證明 ID 與拒絕原因,絕不記錄完整 token、私鑰或敏感資料。指標包括 401/403 比例、nonce 重放、驗證延遲、策略拒絕、預算超限、金鑰輪換失敗與人工審批耗時。
高品質示範回答
我會把系統拆成身份、委託、請求綁定與策略四層。OAuth 或其他簽發系統證明主體關係,委託證明攜帶主體、請求方、權限 profile、過期時間與預算;驗證方再把證明綁定到即將執行的 HTTP 方法、可信 origin、目標 URI、請求摘要與 nonce。
沒有證明時回傳 401 和 WWW-Authenticate: Delegation,帶 no-store;證明有效但權限不足回傳 403。驗證順序是格式、簽章與簽發者信任、nonce 未使用、時間窗口、請求綁定、租戶策略與預算。任何簽章失敗、依賴不可用或 nonce 狀態遺失都預設拒絕。證明本身不定義支付,不取代 HTTP Message Signatures,也不等於 OAuth 的簽發或使用者同意流程。
預算扣減必須與動作提交處於同一交易或可補償邊界;nonce 要原子消費並隔離租戶。公鑰支援輪換與緊急撤銷,日誌只保留證明 ID、主體、目標與結果。驗收關注重放、跨租戶複製、代理改寫、並發超支與金鑰輪換,最終目標是在高影響動作發生前證明「誰代表誰、能對哪條請求做什麼」。
常見錯誤
- 把委託證明當成通用身份認證、OAuth 簽發流程或支付協定。
- 只簽發一個長期 token,不綁定方法、URI、摘要、nonce 與過期時間。
- 在簽章驗證依賴不可用時放行請求,造成故障不安全。
- 忽略代理重寫與不可信
X-Forwarded-*導致的目標混淆。 - 記錄完整憑據或把預算扣減放在動作之後,留下重放與超支窗口。
追問及應對
為什麼需要 401 與 403 兩種回應?
401 表示缺少、無效或不完整的委託證明,客戶端可能透過 challenge 取得新證明;403 表示證明被理解但權限、預算或本地策略不足,重試同一證明沒有意義。
nonce 服務短暫不可用時怎麼辦?
預設拒絕高風險請求,並保留 no-store 的可診斷錯誤。只有經過明確風險評估的低風險唯讀動作才可採用受限降級,不能把快取的舊 nonce 當作一次性狀態。
如何相容 OAuth?
OAuth Token Exchange 或 GNAP 可以負責取得委託材料;驗證層仍獨立檢查 request-bound proof。身份 token 與委託 proof 分別驗證,避免把委託範圍誤當作身份 token 的全部權限。
這是不是支付協定?
不是。預算 profile 可表達金額或服務單位上限,但結算、支付軌道與 HTTP 402 的語義在系統外部定義,驗證層只決定受保護動作是否符合委託策略。