Skip to content

移動端會話存儲:令牌、登出與多賬戶緩存清理

移動端會話問題常在「重新打開應用」後才暴露:舊賬號的緩存短暫閃現,多個請求同時刷新令牌,或用戶登出後後台回調又把舊憑證寫回來。解決它需要把憑證生命週期與業務數據生命週期一起設計。

明確存放與邊界 ​

敏感令牌放在平台安全存儲能力中;普通業務緩存應按用戶 ID 分區,不能僅以介面路徑作為鍵。不要把令牌寫進紀錄、深鏈或可被其他應用讀取的明文文件。啟動時先恢復會話並確認用戶身份,再顯示該用戶的私有緩存。

刷新只允許一個進行中 ​

令牌將過期時,多個請求共享同一個刷新 Promise / Future;刷新成功後繼續請求。若伺服器拒絕刷新,統一失效會話並取消待發送請求,不能讓每個頁面各自彈一次登入框。登出時遞增會話代次:所有帶舊代次的非同步響應即使晚到,也不得寫入新賬戶狀態。

text
session A, epoch 7 → 發出請求
用戶登出 / 切換賬戶 → epoch 8,清理 A 私有緩存
舊請求返回 → epoch 不匹配,丟棄響應

驗證時覆蓋強制關閉應用重啟、時鐘偏差、並行 401、離線登出與快速切換賬號。客戶端防護不能代替伺服器對每個請求的權限檢查。

把會話當成一組可失效的狀態 ​

啓動應用時,不要因為安全存儲里有 token 就立即顯示已登錄頁面。先讀取憑據、確認本地賬號標識,再向服務端驗證或刷新會話;校驗期間頁面處於明確的 restoring 狀態。訪問令牌盡量短壽命,刷新憑據放在系統提供的受保護存儲中;普通偏好設置、日誌和崩潰報告不應包含憑據。需要離線瀏覽時,應事先定義哪些緩存可在未驗證會話時顯示,以及何時必須遮蔽敏感內容。

併發 401 最容易把實現寫亂:五個請求同時發現過期,不能各自刷新並互相覆蓋。讓一個賬戶同一時刻只有一個刷新任務,其餘請求等待同一結果。刷新失敗或服務端撤銷會話時,原子地清掉憑據、賬戶作用域緩存和待執行的敏感操作,再導航到登錄頁。賬號 A 登出後立刻登錄 B,A 的遲到響應和刷新結果必須因會話世代不匹配而丟棄。

text
restoring → authenticated → refreshing → authenticated
                        ↘ refresh rejected → signedOut
signedOut → signingIn → authenticated(new account generation)

明確註銷和離線邊界 ​

用戶主動登出時,先在本地阻斷新的認證請求並清理敏感狀態;若當前離線,服務端撤銷可以排隊或在恢復網絡後執行,但界面必須立即視作已登出。對高風險操作,服務端始終按每次請求重新校驗權限和令牌,不能依賴客戶端頁面是否隱藏按鈕。驗收覆蓋殺進程、設備時間偏差、併發 401、離線登出、A/B 快速切換和刷新憑據輪換。記錄會話狀態轉移及失敗類別,不記錄令牌本身。

MIT Licensed