“同學(xué),我們系統(tǒng)用的是Token認(rèn)證,用戶反饋說經(jīng)常需要重新登錄,體驗很差。你有什么好的續(xù)期方案嗎?順便說說Token該怎么選型?”
上面這段對話,是不是感覺下一秒就會發(fā)生在你的面試中?
別怕,這其實是一道“送分題”。它不僅考驗?zāi)銓τ脩粽J(rèn)證體系的理解深度,更能體現(xiàn)你對系統(tǒng)設(shè)計中安全性與用戶體驗這對“歡喜冤家”的平衡能力。
今天,我們就把Token續(xù)期和選型這點事,一次性講得明明白白。
一、為什么需要續(xù)期?不讓Token永不過期不就行了?
在回答“怎么辦”之前,我們必須先弄清楚“為什么”。
把Token設(shè)置成永不過期?聽起來似乎一勞永逸,但這是一個極其危險的想法。Token本質(zhì)上是一張進(jìn)入你家小區(qū)的“臨時門禁卡”,如果這張卡永不失效,一旦丟失(被黑客竊?。?,后果不堪設(shè)想。
?
所以,Token必須有有效期!
但有效期太短,用戶正用得爽呢,突然就被強制下線,要求重新登錄,那體驗簡直是災(zāi)難。為了解決這個矛盾,“續(xù)期”機制應(yīng)運而生。它的核心目標(biāo)是:在保障安全的前提下,讓用戶感覺不到Token的存在,實現(xiàn)“無感”續(xù)期。
二、續(xù)期三大主流方案,你Pick哪一個?
目前業(yè)界主流的續(xù)期方案有三種,我們逐一分析。
方案一:滑動窗口續(xù)期 (Sliding Session)
這是一種“在你無知無覺中,就幫你把事辦了”的方案。
- 工作方式系統(tǒng)為每個Token設(shè)置一個過期時間(比如30分鐘)。當(dāng)用戶帶著Token來訪問時,如果Token有效,服務(wù)端在返回數(shù)據(jù)的同時,會自動給用戶換發(fā)一個擁有新的30分鐘過期時間的新Token。
- 優(yōu)點實現(xiàn)簡單,邏輯清晰,只要用戶在規(guī)定時間內(nèi)持續(xù)活躍,就能一直在線。
- 缺點
- 安全風(fēng)險如果一個Token被盜,攻擊者也可以通過高頻訪問來讓這個Token“永生”。
- 并發(fā)問題如果用戶同時發(fā)了多個請求,可能會瞬間收到好幾個新Token,客戶端會感到困惑:“我到底該用哪一個?”
- IO壓力對于需要將Token信息存儲在服務(wù)端的普通Token(下文會講),每次續(xù)期都意味著一次寫操作,會增加服務(wù)端IO壓力。
方案二:刷新令牌機制 (Refresh Token) - ?????(強烈推薦)
這是目前最主流、最安全、最推薦的方案,也是你面試時最應(yīng)該拿出來詳談的方案。
核心邏輯:雙令牌解耦(Access Token=訪問權(quán),Refresh Token=續(xù)期權(quán))
它引入了“雙令牌”的概念,把“訪問權(quán)限”和“續(xù)期權(quán)限”解耦。
- 首次登錄
Access Token
訪問令牌,生命周期很短(如1小時),用于API請求時的身份驗證。Refresh Token
刷新令牌,生命周期很長(如7天),專門用來獲取新的Access Token
。
- 日常訪問客戶端每次請求API,都只帶上
Access Token
。 - Access Token過期當(dāng)
Access Token
過期,服務(wù)器返回401 Unauthorized
。 - 靜默刷新客戶端的請求攔截器捕獲到401后,自動攜帶
Refresh Token
去請求一個專門的刷新接口(如/refresh
)。 - 獲取新生服務(wù)器驗證
Refresh Token
有效后,簽發(fā)一個全新的Access Token
,返回給客戶端。 - 無感重試客戶端拿到新的
Access Token
后,重新執(zhí)行剛才失敗的API請求。整個過程對用戶完全透明。
- 極致安全
Access Token
壽命極短,即使泄露,攻擊者也只能猖獗一小會兒。而用于續(xù)命的Refresh Token
只在刷新時才露面,且服務(wù)端可以將其加入黑名單,強制某些用戶下線。 - 體驗與控制兼?zhèn)?/strong>完美解決了用戶體驗與服務(wù)端控制權(quán)的平衡問題。
方案三:服務(wù)端自動續(xù)期
這是一種“愛操心”的服務(wù)端策略。
- 工作方式客戶端正常請求,服務(wù)端在驗證Token的同時,會檢查其剩余有效期。如果發(fā)現(xiàn)有效期不足某個閾值(比如只剩5分鐘了),就在這次請求的響應(yīng)頭里,主動塞一個新的Token給客戶端??蛻舳诵枰獧z查響應(yīng)頭,如果發(fā)現(xiàn)有新Token,就替換掉本地的舊Token。
- 優(yōu)點續(xù)期時機由服務(wù)端掌握,客戶端邏輯相對簡單。
- 缺點屬于“被動”續(xù)期,如果用戶在Token即將過期的幾分鐘內(nèi)恰好沒有任何操作,那么Token還是會過期。此外,每次響應(yīng)都可能需要額外的數(shù)據(jù)傳輸。
三、靈魂拷問:JWT還是普通Token,到底該怎么選?
聊完了續(xù)期,我們必須面對另一個核心問題:你手里的Token,到底是什么類型的?這直接決定了你的系統(tǒng)架構(gòu)。
特性維度 | JWT (JSON Web Token) - “身份證” | 普通 Token - “儲物柜鑰匙” |
核心機制 | 無狀態(tài) (Stateless) Token自身包含所有用戶信息,服務(wù)端無需保存。 | 有狀態(tài) (Stateful) Token只是一個引用ID,用戶信息存在于服務(wù)端(如Redis)。 |
性能/擴展性 | ?高 服務(wù)端驗證簽名即可,無需查庫/緩存。 | ?低 每次請求都需查詢一次DB/緩存,有I/O開銷。 |
安全性 | ??中 Payload部分是明文,嚴(yán)禁存放敏感信息。 | ?高 Token本身無任何意義,信息不外泄。 |
吊銷/注銷 | ?難 過期前始終有效。想讓其提前失效,需引入黑名單。 | ?易 只需從Redis中刪除Token記錄,即可立即失效。 |
微服務(wù) | ?極佳 天然適合微服務(wù)。任何服務(wù)只要有密鑰,就能獨立驗證。 | ?差 所有服務(wù)都需訪問同一個中心化的會話存儲,增加耦合。 |
選型結(jié)論:
- 單體應(yīng)用 & 強管理需求如果你的系統(tǒng)是傳統(tǒng)的單體應(yīng)用,或者需要頻繁地進(jìn)行“強制用戶下線”、“后臺踢人”等強力管控操作,那么普通Token(配合Redis)是你的不二之選。它的控制力無與倫比。
- 微服務(wù)架構(gòu) & 無狀態(tài)API如果你的系統(tǒng)是微服務(wù)架構(gòu),或者追求無狀態(tài)、可無限水平擴展的API,那么請果斷擁抱JWT。它為解耦而生。
四、最佳實踐:Refresh Token + JWT
看到這里,你可能會想,有沒有一種方案能集各家之所長?
當(dāng)然有!那就是 Refresh Token機制
+ JWT
的黃金組合。
這套組合拳的打法是:
Access Token
使用JWT格式充分利用JWT的無狀態(tài)、適合微服務(wù)的特性。同時,將其生命周期設(shè)置得極短(比如15分鐘到1小時),即使泄露,風(fēng)險也極低。Refresh Token
使用普通Token格式它只是一個無意義的隨機字符串,存儲在服務(wù)端(比如Redis或數(shù)據(jù)庫中),并與用戶ID關(guān)聯(lián)。這樣服務(wù)端就擁有了對續(xù)期權(quán)限的絕對控制,可以隨時讓某個Refresh Token
失效。
這個組合,既享受了JWT在業(yè)務(wù)請求中的高性能,又通過Refresh Token
彌補了JWT難以吊銷的短板,同時保證了優(yōu)秀的用戶體驗??胺Q完美!
總結(jié)
回到開頭的面試題,現(xiàn)在你可以自信地給出答案了:
- 闡述續(xù)期的必要性
- 列舉三種續(xù)期方案滑動窗口、Refresh Token(重點講解)、服務(wù)端自動續(xù)期。表明你對Refresh Token方案的青睞,并詳細(xì)闡述其“雙令牌”工作流程和優(yōu)勢。
- 分析Token選型清晰對比JWT和普通Token的優(yōu)劣,并給出在單體應(yīng)用和微服務(wù)架構(gòu)下的選型建議。
- 給出最佳實踐拋出
Refresh Token + JWT
的黃金組合,并解釋它如何取長補短,成為現(xiàn)代應(yīng)用的事實標(biāo)準(zhǔn)。
閱讀原文:https://mp.weixin.qq.com/s/YIF15EpHFAuNko4DvF6bIw
該文章在 2025/9/20 16:10:10 編輯過