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)并注明出處谅年。