題目與適用情境
為一個雙區域 B2B Web 應用程式設計工作階段管理。瀏覽器使用伺服器端工作階段存取一般功能與 管理員功能。產品需要支援登出目前裝置、登出所有裝置,以及密碼變更後的工作階段撤銷。全裝置 登出後,兩個區域都必須在 5 秒內拒絕受保護請求。
本題採用 256 位元不透明識別碼、30 分鐘閒置逾時和 12 小時絕對逾時。這些數字是情境選擇, 並非適用所有產品的安全常數。回答需要說明登入、管理員提權、到期、登出和疑似遭竊時分別發生 什麼,也要涵蓋並行請求與跨區域傳播。
這是一道後端生命週期題。可靠方案讓瀏覽器權杖保持無業務含義,以伺服器端狀態作為認證權威, 在信任邊界變化時更換身分憑證,並能證明舊憑證已失效。Secure、HttpOnly 和 SameSite 都重要,但它們無法單獨提供伺服器端到期、授權或撤銷。
面試官在評估什麼
第一個訊號是候選人是否把工作階段識別碼視為臨時持有者憑證。它必須不可預測,只透過預期機制 接收,在傳輸與儲存中受到保護,也不能進入 URL 與日誌。資料庫或日誌讀取者不應直接取得可用 權杖。
第二個訊號是生命週期推理。匿名識別碼不能原樣升級成登入狀態。登入和提權跨越信任邊界,因此 應用程式要建立新識別碼並銷毀舊值。閒置與絕對到期由伺服器端執行。清除瀏覽器 Cookie 只是 用戶端收尾,無法撤銷攻擊者已複製的值。
第三個訊號是能否區分認證與授權。有效工作階段只負責定位使用者和認證情境;每個請求仍需檢查 目前租戶成員關係與權限。若把角色長期複製進工作階段紀錄,又沒有失效規則,管理員移除角色後 舊權限仍可能繼續生效。
第四個訊號是分散式一致性。承諾全裝置登出 5 秒內生效,需要權威版本或撤銷狀態、有上限的快取 陳舊時間,以及分割時的明確行為。若另一區域還能使用已快取的有效結果,只說「從 Redis 刪除」 並不完整。
最後看驗證能力。候選人要把工作階段固定、竊取、CSRF、到期、並行輪替、副本延遲和日誌洩漏 變成可執行測試。每個舊識別碼都應有一個明確事件,事件之後再使用它必須失敗。
回答前要先確認的問題
- 哪些用戶端在範圍內? 本回答針對同站點瀏覽器應用程式。原生 App 和第三方 API 用戶端
通常需要不同的權杖傳輸與生命週期。
- 「5 秒內」具體指什麼? 伺服器端必須在期限內拒絕受保護請求;瀏覽器分頁可在下一次請求
前繼續顯示舊內容。
- 是否允許同時登入多台裝置? 本方案允許並分別儲存每個工作階段。更嚴格的產品可以限制
數量,或在新登入時替換舊工作階段。
- 哪些事件撤銷全部工作階段? 全裝置登出和變更密碼會遞增帳戶級工作階段 epoch。權限變化
可只遞增授權版本,不一定強制所有裝置登出。
- 管理員存取風險多高? 本方案在提權時輪替,並記錄認證強度。高影響操作還可要求近期重新
認證。
- 是否需要跨站登入或嵌入? 假設第一方導覽使用
SameSite=Lax。合法跨站流程需要最小化
例外,並增加明確的 CSRF 防護。
- 區域分割時怎麼辦? 5 秒安全要求意味著高風險路由無法取得新鮮撤銷狀態時要失敗關閉。
30 秒回答架構
「我會把 256 位元不透明值放進帶 Secure、HttpOnly、Path=/ 和明確 SameSite 策略的 __Host- Cookie,伺服器端只儲存經過 HMAC 衍生的查詢鍵。工作階段列記錄使用者、租戶、 認證強度、建立與活動時間、到期時間,以及使用者的工作階段版本和授權版本。登入和管理員提權 都會原子地建立新工作階段並讓舊識別碼失效。每個受保護請求都檢查閒置與絕對到期、目前帳戶 epoch 和目前權限。目前裝置登出撤銷該列;全裝置登出或變更密碼遞增帳戶 epoch,並把失效訊息 傳播到兩個區域,正向快取上限為 5 秒。最後驗證工作階段固定、舊 ID 重放、並行輪替、CSRF、 逾時邊界、區域延遲和日誌脫敏。」
分步驟深入解答
先建立威脅模型。攻擊者可能在受害者登入前設定識別碼,從瀏覽器或基礎設施竊取識別碼,在另一 裝置重放,透過持續請求延長其生命,利用陳舊權限,或與輪替請求競爭。瀏覽器會自動攜帶 Cookie, 因此系統也要防止跨站狀態變更請求。
優先使用框架中經過審查的工作階段實作,不要自行發明亂數產生與解析邏輯。在本情境中,用密碼學 安全亂數產生器產生 32 個隨機位元組。原始不透明值只進入 Cookie。查詢儲存前,計算類似 HMAC-SHA-256(serverkey, rawid) 的固定長度鍵,讓資料庫快照不直接包含持有者值。HMAC 金鑰輪替也要有明確的雙讀遷移方案。
伺服器端紀錄可包含:
session_lookup_key
user_id, tenant_id
created_at, last_seen_at
idle_expires_at, absolute_expires_at
authentication_time, authentication_strength
session_epoch, authorization_version
revoked_at, revocation_reason瀏覽器收到僅限目前主機的 Cookie:
Set-Cookie: __Host-session=<opaque>; Secure; HttpOnly; SameSite=Lax; Path=/__Host- 前綴要求 Secure、禁止 Domain 並要求 Path=/,能減少子網域注入 Cookie。 HttpOnly 阻止 JavaScript 直接讀取,卻不能阻止注入指令碼發起已認證操作。SameSite 只能 減少部分跨站請求,是縱深防禦;狀態變更路由仍需 CSRF 權杖或其他與請求綁定的證明,並在適當 位置驗證 Origin。
工作階段只從 Cookie 接收。除非獨立用戶端協定明確規定,否則拒絕 URL 參數或其他標頭中的 工作階段 ID。URL 會進入歷史、Referer、分析系統、截圖與代理日誌。驗證識別碼格式,保持失敗 回應形狀一致,並限制重複無效識別碼的請求速率。
匿名狀態與登入狀態要分開。憑證驗證成功後,在短交易中建立新的認證工作階段,並讓登入前識別碼 失效。管理員提權或其他權限增加時,先取得相應證明,再建立全新識別碼,讓低信任識別碼失效。 只有伺服器端狀態提交成功,回應才設定新 Cookie。
瀏覽器並行請求讓輪替更棘手。若立即銷毀舊識別碼,仍在途的請求可能收到未登入回應。可在幾秒內 把舊識別碼對應到已建立的唯一後繼者,但對應絕不能產生多個後繼者,也不能把新持有者值回傳給 任意重放者。使用一筆原子輪替紀錄,只透過合法回應交付後繼值。對敏感提權而言,讓失敗請求 重試通常比設定寬鬆寬限期更安全。
每個受保護請求都查詢工作階段,拒絕已撤銷列,用伺服器時間執行兩個到期時鐘,並比較 session_epoch 與帳戶目前 epoch。30 分鐘閒置時限只在有意義的活動後推進,可分桶更新, 避免每個請求都寫入。12 小時絕對期限永不推進。用戶端倒數可以改善體驗,但不能決定工作階段 是否有效。
接著載入目前租戶成員與授權狀態,或比較具有明確失效契約的版本號。有效工作階段永遠不能取代 物件級授權。IP、網路、裝置和 User-Agent 變化適合作為風險訊號;硬性綁定會讓行動網路、代理 和共享裝置頻繁誤登出。高風險變化可依策略觸發重新認證或工作階段撤銷。
登出目前裝置時,先原子標記伺服器端工作階段已撤銷,再讓 Cookie 到期。全裝置登出與變更密碼 遞增使用者的 session_epoch,所有舊工作階段隨即不符,即使個別工作階段列仍存在。將新 epoch 發布到兩個區域並清除正向快取。快取生命上限不超過 5 秒;管理員等高風險路由在快取過舊時讀取 權威狀態。區域分割時這些路由失敗關閉,因為可用性不能推翻題目中的撤銷保證。
沒有測量就不能承諾 5 秒。記錄權威提交時間和每個區域首次拒絕舊工作階段的時間,傳播時間接近 預算時警示。稽核工作階段建立、輪替、提權、到期和撤銷時使用非敏感關聯 ID,絕不記錄原始 Cookie、查詢鍵或完整 Cookie 標頭。
圍繞狀態轉移建立測試。預設攻擊者選擇的匿名 Cookie,完成登入,證明它無法存取帳戶。重放 登入前、提權前、已登出、已到期和變更密碼前的 ID。使用可控制的伺服器時鐘驗證閒置與絕對 逾時邊界。並行發起兩次提權,延遲一個區域的失效訊息,模擬分割,傳送跨站請求,並掃描應用、 代理、追蹤、分析和客服日誌,確認沒有持有者值。
高品質示範回答
「我會把工作階段建模為伺服器端狀態機,瀏覽器句柄只是臨時持有者憑證。本題中句柄由 32 個 隨機位元組組成。Cookie 僅限目前主機、只走 HTTPS、JavaScript 不可讀、作用於根路徑並明確 使用 SameSite=Lax;工作階段儲存只接收 HMAC 衍生的查詢鍵。
紀錄包含使用者和租戶、認證強度、建立與最近活動時間、30 分鐘閒置期限、固定 12 小時絕對 期限,以及帳戶工作階段 epoch 和授權版本快照。每個請求都驗證工作階段列、兩個期限、目前 epoch 和目前權限。IP 與裝置變化只進入風險判斷,不作為脆弱的身分憑證。
登入和管理員提權都會建立新工作階段並使低信任識別碼失效。輪替是原子的,因此並行請求不能 建立彼此競爭的後繼者。登出先撤銷伺服器端列,再清除 Cookie。全裝置登出和變更密碼遞增帳戶 epoch,並發布快取失效。兩個區域的正向快取最長 5 秒;高風險路由無法重新整理狀態時失敗關閉。
最後,我會測試工作階段固定、每個歷史識別碼的重放、CSRF、並行輪替、閒置與絕對時限邊界、 權限變化、區域傳播、分割行為和無敏感資訊日誌。關鍵證據是:每次信任變化都有明確的舊憑證, 也有可測量的時間點,過了該點舊憑證必然被拒絕。」
常見錯誤
- 登入後沿用同一 ID → 攻擊者可提前植入並等待認證 → **建立新的認證工作階段並銷毀匿名
工作階段。**
- 登出時只清除 Cookie → 遭竊副本仍然有效 → 先撤銷伺服器端狀態,再清除用戶端狀態。
- 把
HttpOnly當成 XSS 防護 → 注入指令碼仍可發起認證請求 → **獨立防 XSS,並執行
授權和 CSRF 防護。**
- 只靠
SameSite防 CSRF → 合法例外和瀏覽器行為會削弱假設 → **狀態變更使用請求綁定
的 CSRF 證明。**
- 把 ID 放進 URL → 歷史、Referer 和日誌會複製憑證 → 只透過預期 Cookie 機制接收。
- 只重新整理閒置期限 → 活躍的竊取者可無限使用 → 另設固定絕對期限。
- 無限快取有效工作階段 → 全裝置登出無法滿足時限 → **使用工作階段版本,並限制或繞過
正向快取。**
- 把角色永久寫進工作階段 → 已移除權限仍會保留 → 檢查目前權限或可明確失效的版本。
- 硬性綁定 IP 位址 → 一般網路變化導致誤登出 → 把情境變化作為風險訊號。
- 設定寬鬆輪替寬限期 → 兩個持有者值會同時可用 → **使用原子且極短的交接,或讓敏感
提權請求重試。**
- 為除錯記錄 Cookie 標頭 → 可觀測系統變成憑證倉庫 → 只記錄非敏感關聯值。
追問與回答
追問 1:為什麼使用伺服器端工作階段,而不是自包含 JWT?
題目要求全裝置及時撤銷,本來就需要讀取目前伺服器端狀態。不透明識別碼不會把宣告交給瀏覽器, 單列撤銷也直接。JWT 可以使用,但立即登出仍需要短到期、撤銷清單或帳戶版本查詢;簽章本身 解決不了撤銷。
追問 2:如何避免每個請求都為重新整理閒置期限寫入?
把權威最近活動時間按粗粒度分桶,例如只有儲存值已經過數分鐘才更新。伺服器端仍會在衍生的 閒置期限到達後拒絕工作階段。分桶可能帶來的最大延長必須寫進安全策略,並專門測試該邊界。
追問 3:跨區域儲存不可用時怎麼辦?
按路由風險區分。若策略允許,公開或唯讀路由可接受有上限的快取判斷。管理員和其他高影響路由 必須取得新鮮 epoch,否則失敗關閉;繼續放行會讓 5 秒全裝置登出承諾失真。這個行為同時納入 可用性和安全 SLO。
追問 4:是否應該始終週期性輪替工作階段 ID?
不應該。週期輪替能縮短單個遭竊 ID 的利用時間,卻會引入交接競態,也無法取代閒置和絕對到期。 先保證登入和提權時輪替。只有威脅模型收益明確、原子協定經過測試時,才增加週期輪替。
追問 5:如何向使用者顯示目前登入裝置?
儲存建立時間、最近活動時間桶、大致裝置標籤和粗粒度位置等非敏感中繼資料。使用者可以撤銷單列, 或遞增帳戶 epoch 登出全部裝置。標籤只是提示,不是裝置身分憑證;原始工作階段 ID 永遠不進入 介面或稽核匯出。
追問 6:哪個測試最能暴露工作階段固定?
在認證前植入一個指定識別碼,完成登入,再從另一用戶端用舊值請求受保護資源。舊值必須失敗, 新簽發值必須成功。對管理員提權重複測試,並確認儲存和日誌都沒有洩漏替換後的持有者值。