後端面試:如何安全處理 HTTP 425 Too Early 與 0-RTT 重放?
題干與適用場景
支付 API 啟用 TLS 1.3 會話恢復。部分請求在連線尚未完成握手時到達,閘道回傳 425 Too Early。請說明哪些請求可以使用早期資料、如何避免重放副作用、代理如何傳遞訊號,以及用戶端何時可以重試。
面試官考察點
- 是否理解 0-RTT 追求延遲,卻不能提供普通握手同等的重放保護。
- 能否區分 425、網路逾時與業務拒絕,並正確使用
Early-Data: 1。 - 能否把冪等鍵、去重窗口、閘道策略與伺服器狀態機連成閉環。
- 能否用指標與演練證明重試沒有重複扣款。
回答前需要釐清的問題
- 用戶端、CDN、閘道與源站誰終止 TLS,誰能判斷請求是否處於早期資料?
- 請求是 GET、查詢,還是會扣款、出貨、寫入訊息的副作用操作?
- 是否有全域唯一冪等鍵,去重記錄保存多久,跨區域是否共享?
- 425 是否由閘道統一回傳,SDK 是否理解它並能重建請求主體?
- 重試截止時間、支付授權有效期與使用者可見狀態如何對齊?
30 秒回答框架
0-RTT 讓用戶端在 TLS 1.3 恢復會話時提前傳送應用資料,但資料可能被攻擊者重放。伺服器對有副作用的請求預設拒絕早期資料;代理可用 Early-Data: 1 表示請求經過早期資料,並回傳 425。用戶端完成普通握手後只重試可安全重放的請求;支付類請求必須先用冪等鍵查詢結果或等待業務確認,不能把 425 當作扣款失敗。
分步深入解答
第一步:定義 0-RTT 邊界
TLS 1.3 會話恢復允許用戶端傳送 early data,以減少一次往返延遲。伺服器不能把它當成新鮮且不可重放的證明;攻擊者可能在允許窗口內複製同一段資料再次傳送。
第二步:按副作用分類
公開 GET、唯讀查詢或具備嚴格冪等語義的請求,在符合協定與業務條件時才考慮 early data。扣款、建立訂單、發放權益、傳送訊息等操作預設停用,除非伺服器有可靠的冪等鍵與原子去重。
第三步:理解 Early-Data 與 425
支援早期資料的中間層可在轉發請求時加入 Early-Data: 1。源站不願承擔重放風險時回傳 425,表示請求過早,用戶端應在握手完成後重新傳送。沒有此標頭不代表請求絕對沒有重放風險,仍需確認端到端部署。
第四步:設計閘道策略
閘道按方法、路徑與認證類型建立白名單。支付、庫存與權限變更路徑直接禁止 early data;唯讀路徑可放行並記錄連線狀態。閘道不能把 425 改成普通 500,否則 SDK 無法採取正確動作。
第五步:設計冪等與去重
用戶端為每次業務意圖產生不可預測的冪等鍵,伺服器在提交副作用與寫入去重記錄時使用同一事務或等價原子機制。重複鍵回傳第一次結果,不能重新執行扣款。去重 TTL 要覆蓋最大網路重試、佇列延遲與對帳窗口。
第六步:規定安全重試
收到 425 後先建立完整連線,再重放仍在截止時間內且主體可重建的請求。GET 可自動重試;帶冪等鍵的支付請求先查詢冪等狀態再決定;沒有冪等保障的寫請求交由業務確認。每個意圖設定一次重試上限與退避。
第七步:驗證與觀測
記錄 early-data 請求數、425 比例、按路徑重試率、重複冪等鍵、扣款成功與退款對帳差異。以代理鏈與故障注入測試早期資料被拒、普通握手重試、用戶端逾時、重複請求及跨區域去重,驗收必須證明每個業務意圖最多產生一次副作用。
高品質示範回答
我會先把支付寫入路徑加入 early-data 禁止名單。TLS 終止層若收到早期資料,向源站傳送 Early-Data: 1;源站對這類寫入回傳 425,並保留可診斷的請求 ID。用戶端完成普通握手後不盲目重放:它用冪等鍵查詢訂單或扣款狀態,狀態未知才在截止時間內重試一次。伺服器將冪等鍵、業務結果與去重記錄原子落庫,跨區域共享去重邊界。唯讀 GET 可自動重試,所有路徑監控 425、重複鍵與支付對帳差異,以演練證明沒有重複扣款。
常見錯誤
- 認為 TLS 1.3 的 0-RTT 天然防重放。
- 收到 425 就無限重試,或把它改寫成 500。
- 只按 HTTP 方法判斷安全,忽略某些 GET 也可能觸發副作用。
- 冪等鍵只存在用戶端,伺服器沒有原子去重與結果保存。
- 用「請求未到達」假設處理逾時,未先查詢業務狀態。
追問及應對
追問一:425 與 503 有什麼區別?
425 針對早期資料的重放風險,暗示完成握手後可以重新評估;503 表示服務暫時不可用,重試依據是服務能力與 Retry-After,兩者不能互換。
追問二:Early-Data 標頭由誰加入?
理解此機制的中間層在把早期資料轉發給源站時加入 Early-Data: 1。部署必須核實 TLS 終止點與代理是否保留或偽造該訊號。
追問三:支付請求有冪等鍵就能放心使用 0-RTT 嗎?
不能直接放心。還要保證鍵不可預測、去重記錄原子持久化、跨區域一致性與 TTL 足夠長,並驗證重複鍵回傳同一結果。
追問四:用戶端逾時後為什麼先查詢?
逾時只說明用戶端沒有收到結果,不能證明伺服器沒有提交。查詢冪等狀態可區分已成功、處理中與未執行,避免重複扣款。
追問五:如何做灰度?
先在唯讀路徑與小流量用戶端啟用,按路徑記錄 425 與重試成功率;任何重複副作用、異常對帳或跨代理訊號缺失都應自動關閉 early data。