常用的使用者認證方式 詳解JWT

2021-10-08 14:52:38 字數 3200 閱讀 4056

和session的區別和優缺點

總結authentication:使用者認證,指的是驗證使用者的身份,例如你希望以小a的身份登入,那麼應用程式需要通過使用者名稱和密碼確認你真的是小a。

由於http協議是無狀態的,每一次請求都無狀態。當乙個使用者通過使用者名稱和密碼登入了之後,他的下乙個請求不會攜帶任何狀態,應用程式無法知道他的身份,那就必須重新認證。因此我們希望使用者登入成功之後的每一次http請求,都能夠儲存他的登入狀態。

目前主流的使用者認證方法有基於token和基於session兩種方式。

1、基於session的使用者認證

之前的一篇 文章 總結過

2、基於token(令牌)的使用者認證

最常用的是json web token(jwt)

使用者輸入其登入資訊

伺服器驗證資訊是否正確,並返回已簽名的token

token儲在客戶端,例如存在local storage或cookie中

之後的http請求都將token新增到請求頭里

伺服器解碼jwt,並且如果令牌有效,則接受請求

一旦使用者登出,令牌將在客戶端被銷毀,不需要與伺服器進行互動乙個關鍵是,令牌是無狀態的。後端伺服器不需要儲存令牌或當前session的記錄。

乙個jwt實際上就是乙個字串,它由三部分組成,頭部、載荷與簽名,這三個部分都是json格式。

1、頭部(header):

頭部用於描述關於該jwt的最基本的資訊,例如其型別以及簽名所用的演算法等。

在這裡,我們說明了這是乙個jwt,並且我們所用的簽名演算法是hs256演算法。

2、載荷(payload)

載荷可以用來放一些不敏感的資訊。

這裡面的前五個欄位都是由jwt的標準所定義的。

iss: 該jwt的簽發者

sub: 該jwt所面向的使用者

aud: 接收該jwt的一方

exp(expires): 什麼時候過期,這裡是乙個unix時間戳

iat(issued at): 在什麼時候簽發的

把頭部和載荷分別進行base64編碼之後得到兩個字串,然後再將這兩個編碼後的字串用英文句號.連線在一起(頭部在前),形成新的字串:

eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjmcm9tx3vzzxiioijciiwidgfyz2v0x3vzzxiioijbin0
3、簽名(signature)

最後,我們將上面拼接完的字串用hs256演算法進行加密。在加密的時候,我們還需要提供乙個金鑰(secret)。加密後的內容也是乙個字串,最後這個字串就是簽名,把這個簽名拼接在剛才的字串後面就能得到完整的jwt。header部分和payload部分如果被篡改,由於篡改者不知道金鑰是什麼,也無法生成新的signature部分,服務端也就無法通過,在jwt中,訊息體是透明的,使用簽名可以保證訊息不被篡改。

eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjmcm9tx3vzzxiioijciiwidgfyz2v0x3vzzxiioijbin0.rswamyaywuhco7ifagd1orpsp7nzl7bf5t7itqpkvim
使用者的狀態儲存的位置:

session是儲存在服務端的,而jwt是儲存在客戶端的。

優點:1、 可擴充套件性好

應用程式分布式部署的情況下,session需要做多機資料共享,通常可以存在資料庫或者redis裡面。而jwt不需要。

2、 無狀態

jwt不在服務端儲存任何狀態。restful api的原則之一是無狀態,發出請求時,總會返回帶有引數的響應,不會產生附加影響。使用者的認證狀態引入這種附加影響,這破壞了這一原則。另外jwt的載荷中可以儲存一些常用資訊,用於交換資訊,有效地使用 jwt,可以降低伺服器查詢資料庫的次數。

缺點:1、 安全性

由於jwt的payload是使用base64編碼的,並沒有加密,因此jwt中不能儲存敏感資料。而session的資訊是存在服務端的,相對來說更安全。

2、 效能

jwt太長。由於是無狀態使用jwt,所有的資料都被放到jwt裡,如果還要進行一些資料交換,那載荷會更大,經過編碼之後導致jwt非常長,cookie的限制大小一般是4k,cookie很可能放不下,所以jwt一般放在local storage裡面。並且使用者在系統中的每一次http請求都會把jwt攜帶在header裡面,http請求的header可能比body還要大。而sessionid只是很短的乙個字串,因此使用jwt的http請求比使用session的開銷大得多。

3、 一次性

無狀態是jwt的特點,但也導致了這個問題,jwt是一次性的。想修改裡面的內容,就必須簽發乙個新的jwt。

(1)無法廢棄

通過上面jwt的驗證機制可以看出來,一旦簽發乙個jwt,在到期之前就會始終有效,無法中途廢棄。例如你在payload中儲存了一些資訊,當資訊需要更新時,則重新簽發乙個jwt,但是由於舊的jwt還沒過期,拿著這個舊的jwt依舊可以登入,那登入後服務端從jwt中拿到的資訊就是過時的。為了解決這個問題,我們就需要在服務端部署額外的邏輯,例如設定乙個黑名單,一旦簽發了新的jwt,那麼舊的就加入黑名單(比如存到redis裡面),避免被再次使用。

(2)續簽

如果你使用jwt做會話管理,傳統的cookie續簽方案一般都是框架自帶的,session有效期30分鐘,30分鐘內如果有訪問,有效期被重新整理至30分鐘。一樣的道理,要改變jwt的有效時間,就要簽發新的jwt。最簡單的一種方式是每次請求重新整理jwt,即每個http請求都返回乙個新的jwt。這個方法不僅暴力不優雅,而且每次請求都要做jwt的加密解密,會帶來效能問題。另一種方法是在redis中單獨為每個jwt設定過期時間,每次訪問時重新整理jwt的過期時間。

可以看出想要破解jwt一次性的特性,就需要在服務端儲存jwt的狀態。但是引入 redis 之後,就把無狀態的jwt硬生生變成了有狀態了,違背了jwt的初衷。而且這個方案和session都差不多了。

適合使用jwt的場景:

比如,使用者註冊後發一封郵件讓其啟用賬戶,通常郵件中需要有乙個鏈結,這個鏈結需要具備以下的特性:能夠標識使用者,該鏈結具有時效性(通常只允許幾小時之內啟用),不能被篡改以啟用其他可能的賬戶,一次性的。這種場景就適合使用jwt。

而由於jwt具有一次性的特性。單點登入和會話管理非常不適合用jwt,如果在服務端部署額外的邏輯儲存jwt的狀態,那還不如使用session。基於session有很多成熟的框架可以開箱即用,但是用jwt還要自己實現邏輯。

DRF的JWT使用者認證

目錄jwt的使用 從根本上來說,jwt是一種開放的標準 rfc 7519 全稱為json web token 其存在的意義在於,對於前後端分離的專案來說,後端不需要儲存token,主需要儲存簽發和校驗token的演算法,所以我們需要在前端儲存token,然後通過jwt加密之後傳送給後端,從而完成校驗...

使用者認證 基於jwt和session的區別和優缺點

背景知識 authentication和authorization的區別 authentication 使用者認證,指的是驗證使用者的身份,例如你希望以小a的身份登入,那麼應用程式需要通過使用者名稱和密碼確認你真的是小a。由於http協議是無狀態的,每一次請求都無狀態。當乙個使用者通過使用者名稱和密...

基於token認證的JWT方案

後端校驗使用者名稱密碼,生成token返回給前端,有時也會儲存token到使用者表或者儲存到全域性map中 toekn的生成規則一般是base64 uid md5 u pwd secret 前端拿到token之後,儲存到localstrage中 前端再請求的時候要把token放到header來過來 ...