基于 JWT + Refresh Token 的用戶認證實踐

HTTP 是一個無狀態(tài)的協(xié)議庭瑰,一次請求結(jié)束后,下次在發(fā)送服務(wù)器就不知道這個請求是誰發(fā)來的了(同一個 IP 不代表同一個用戶)抢埋,在 Web 應(yīng)用中弹灭,用戶的認證和鑒權(quán)是非常重要的一環(huán),實踐中有多種可用方案揪垄,并且各有千秋穷吮。

基于 Session 的會話管理

在 Web 應(yīng)用發(fā)展的初期,大部分采用基于 Session 的會話管理方式饥努,邏輯如下捡鱼。

  • 客戶端使用用戶名密碼進行認證
  • 服務(wù)端生成并存儲 Session,將 SessionID 通過 Cookie 返回給客戶端
  • 客戶端訪問需要認證的接口時在 Cookie 中攜帶 SessionID
  • 服務(wù)端通過 SessionID 查找 Session 并進行鑒權(quán)酷愧,返回給客戶端需要的數(shù)據(jù)

基于 Session 的方式存在多種問題驾诈。

  • 服務(wù)端需要存儲 Session,并且由于 Session 需要經(jīng)橙茉。快速查找乍迄,通常存儲在內(nèi)存或內(nèi)存數(shù)據(jù)庫中,同時在線用戶較多時需要占用大量的服務(wù)器資源士败。
  • 當(dāng)需要擴展時闯两,創(chuàng)建 Session 的服務(wù)器可能不是驗證 Session 的服務(wù)器,所以還需要將所有 Session 單獨存儲并共享。
  • 由于客戶端使用 Cookie 存儲 SessionID漾狼,在跨域場景下需要進行兼容性處理重慢,同時這種方式也難以防范 CSRF 攻擊。

基于 Token 的會話管理

鑒于基于 Session 的會話管理方式存在上述多個缺點逊躁,無狀態(tài)的基于 Token 的會話管理方式誕生了伤锚,所謂無狀態(tài),就是服務(wù)端不再存儲信息志衣,甚至是不再存儲 Session,邏輯如下猛们。

  • 客戶端使用用戶名密碼進行認證
  • 服務(wù)端驗證用戶名密碼念脯,通過后生成 Token 返回給客戶端
  • 客戶端保存 Token,訪問需要認證的接口時在 URL 參數(shù)或 HTTP Header 中加入 Token
  • 服務(wù)端通過解碼 Token 進行鑒權(quán)弯淘,返回給客戶端需要的數(shù)據(jù)

基于 Token 的會話管理方式有效解決了基于 Session 的會話管理方式帶來的問題绿店。

  • 服務(wù)端不需要存儲和用戶鑒權(quán)有關(guān)的信息,鑒權(quán)信息會被加密到 Token 中庐橙,服務(wù)端只需要讀取 Token 中包含的鑒權(quán)信息即可
  • 避免了共享 Session 導(dǎo)致的不易擴展問題
  • 不需要依賴 Cookie假勿,有效避免 Cookie 帶來的 CSRF 攻擊問題
  • 使用 CORS 可以快速解決跨域問題

JWT 介紹

JWT 是 JSON Web Token 的縮寫,JWT 本身沒有定義任何技術(shù)實現(xiàn)态鳖,它只是定義了一種基于 Token 的會話管理的規(guī)則转培,涵蓋 Token 需要包含的標(biāo)準(zhǔn)內(nèi)容和 Token 的生成過程。

一個 JWT Token 長這樣浆竭。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDQ1MTE3NDMsImp0aSI6IjYxYmVmNjkyLTE4M2ItNGYxYy1hZjE1LWUwMDM0MTczNzkxOSJ9.CZzB2-JI1oPRFxNMaoFz9-9cKGTYVXkOC2INMoEYNNA

仔細辨別會發(fā)現(xiàn)它由 A.B.C 三部分組成浸须,這三部分依次是頭部(Header)、負載(Payload)邦泄、簽名(Signature)删窒,頭部和負載以 JSON 形式存在,這就是 JWT 中的 JSON顺囊,三部分的內(nèi)容都分別單獨經(jīng)過了 Base64 編碼肌索,以 . 拼接成一個 JWT Token。

JWT 的 Header 中存儲了所使用的加密算法和 Token 類型特碳。

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload 是負載诚亚,JWT 規(guī)范規(guī)定了一些字段,并推薦使用测萎,開發(fā)者也可以自己指定字段和內(nèi)容亡电,例如下面的內(nèi)容。

{
  username: 'yage',
  email: 'sa@simpleapples.com',
  role: 'user',
  exp: 1544602234
}

需要注意的是硅瞧,Payload的內(nèi)容只經(jīng)過了 Base64 編碼份乒,對客戶端來說當(dāng)于明文存儲,所以不要放置敏感信息。

Signature 部分用來驗證 JWT Token 是否被篡改或辖,所以這部分會使用一個 Secret 將前兩部分加密瘾英,邏輯如下。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT 優(yōu)勢 & 問題

JWT 擁有基于 Token 的會話管理方式所擁有的一切優(yōu)勢颂暇,不依賴 Cookie缺谴,使得其可以防止 CSRF 攻擊,也能在禁用 Cookie 的瀏覽器環(huán)境中正常運行耳鸯。

而 JWT 的最大優(yōu)勢是服務(wù)端不再需要存儲 Session湿蛔,使得服務(wù)端認證鑒權(quán)業(yè)務(wù)可以方便擴展,避免存儲 Session 所需要引入的 Redis 等組件县爬,降低了系統(tǒng)架構(gòu)復(fù)雜度阳啥。但這也是 JWT 最大的劣勢,由于有效期存儲在 Token 中财喳,JWT Token 一旦簽發(fā)察迟,就會在有效期內(nèi)一直可用,無法在服務(wù)端廢止耳高,當(dāng)用戶進行登出操作扎瓶,只能依賴客戶端刪除掉本地存儲的 JWT Token,如果需要禁用用戶泌枪,單純使用 JWT 就無法做到了概荷。

基于 JWT 的實踐

既然 JWT 依然存在諸多問題,甚至無法滿足一些業(yè)務(wù)上的需求工闺,但是我們依然可以基于 JWT 在實踐中進行一些改進乍赫,來形成一個折中的方案,畢竟陆蟆,在用戶會話管理場景下雷厂,沒有銀彈。

前面講的 Token叠殷,都是 Access Token改鲫,也就是訪問資源接口時所需要的 Token,還有另外一種 Token林束,Refresh Token像棘,通常情況下,Refresh Token 的有效期會比較長壶冒,而 Access Token 的有效期比較短缕题,當(dāng) Access Token 由于過期而失效時,使用 Refresh Token 就可以獲取到新的 Access Token胖腾,如果 Refresh Token 也失效了烟零,用戶就只能重新登錄了瘪松。

在 JWT 的實踐中,引入 Refresh Token锨阿,將會話管理流程改進如下宵睦。

  • 客戶端使用用戶名密碼進行認證
  • 服務(wù)端生成有效時間較短的 Access Token(例如 10 分鐘),和有效時間較長的 Refresh Token(例如 7 天)
  • 客戶端訪問需要認證的接口時墅诡,攜帶 Access Token
  • 如果 Access Token 沒有過期壳嚎,服務(wù)端鑒權(quán)后返回給客戶端需要的數(shù)據(jù)
  • 如果攜帶 Access Token 訪問需要認證的接口時鑒權(quán)失敗(例如返回 401 錯誤)末早,則客戶端使用 Refresh Token 向刷新接口申請新的 Access Token
  • 如果 Refresh Token 沒有過期烟馅,服務(wù)端向客戶端下發(fā)新的 Access Token
  • 客戶端使用新的 Access Token 訪問需要認證的接口

將生成的 Refresh Token 以及過期時間存儲在服務(wù)端的數(shù)據(jù)庫中,由于 Refresh Token 不會在客戶端請求業(yè)務(wù)接口時驗證然磷,只有在申請新的 Access Token 時才會驗證焙糟,所以將 Refresh Token 存儲在數(shù)據(jù)庫中,不會對業(yè)務(wù)接口的響應(yīng)時間造成影響样屠,也不需要像 Session 一樣一直保持在內(nèi)存中以應(yīng)對大量的請求。

上述的架構(gòu)缺脉,提供了服務(wù)端禁用用戶 Token 的方式痪欲,當(dāng)用戶需要登出或禁用用戶時,只需要將服務(wù)端的 Refresh Token 禁用或刪除攻礼,用戶就會在 Access Token 過期后业踢,由于無法獲取到新的 Access Token 而再也無法訪問需要認證的接口。這樣的方式雖然會有一定的窗口期(取決于 Access Token 的失效時間)礁扮,但是結(jié)合用戶登出時客戶端刪除 Access Token 的操作知举,基本上可以適應(yīng)常規(guī)情況下對用戶認證鑒權(quán)的精度要求。

總結(jié)

JWT 的使用太伊,提高了開發(fā)者開發(fā)用戶認證鑒權(quán)功能的效率雇锡,降低了系統(tǒng)架構(gòu)復(fù)雜度,避免了大量的數(shù)據(jù)庫和緩存查詢僚焦,降低了業(yè)務(wù)接口的響應(yīng)延遲锰提。然而 JWT 的這些優(yōu)點也增加了 Token 管理上的難度,通過引入 Refresh Token芳悲,既能繼續(xù)使用 JWT 所帶來的優(yōu)勢立肘,又能使得 Token 管理的精度符合業(yè)務(wù)的需求。

作者:simpleapples
鏈接:http://www.reibang.com/p/25ab2f456904
來源:簡書
簡書著作權(quán)歸作者所有名扛,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處谅年。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肮韧,隨后出現(xiàn)的幾起案子融蹂,更是在濱河造成了極大的恐慌旺订,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殿较,死亡現(xiàn)場離奇詭異耸峭,居然都是意外死亡,警方通過查閱死者的電腦和手機淋纲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門劳闹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洽瞬,你說我怎么就攤上這事本涕。” “怎么了伙窃?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵菩颖,是天一觀的道長。 經(jīng)常有香客問我为障,道長晦闰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任鳍怨,我火速辦了婚禮呻右,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鞋喇。我一直安慰自己声滥,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布侦香。 她就那樣靜靜地躺著落塑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪罐韩。 梳的紋絲不亂的頭發(fā)上憾赁,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音散吵,去河邊找鬼缠沈。 笑死,一個胖子當(dāng)著我的面吹牛错蝴,可吹牛的內(nèi)容都是我干的洲愤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼顷锰,長吁一口氣:“原來是場噩夢啊……” “哼柬赐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起官紫,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肛宋,失蹤者是張志新(化名)和其女友劉穎州藕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酝陈,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡床玻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沉帮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锈死。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖穆壕,靈堂內(nèi)的尸體忽然破棺而出待牵,到底是詐尸還是另有隱情,我是刑警寧澤喇勋,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布缨该,位于F島的核電站,受9級特大地震影響川背,放射性物質(zhì)發(fā)生泄漏贰拿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一熄云、第九天 我趴在偏房一處隱蔽的房頂上張望壮不。 院中可真熱鬧,春花似錦皱碘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至菱阵,卻和暖如春踢俄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晴及。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工都办, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虑稼。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓琳钉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛛倦。 傳聞我的和親對象是個殘疾皇子歌懒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容