1. 程式人生 > >傳統身份驗證和JWT的身份驗證

傳統身份驗證和JWT的身份驗證

轉自:https://ninghao.net/blog/2834

1、傳統身份驗證和JWT的身份驗證

傳統身份驗證:

      HTTP 是一種沒有狀態的協議,也就是它並不知道是誰是訪問應用。這裡我們把使用者看成是客戶端,客戶端使用使用者名稱還有密碼通過了身份驗證,不過下回這個客戶端再發送請求時候,還得再驗證一下。
    解決的方法就是,當用戶請求登入的時候,如果沒有問題,我們在服務端生成一條記錄,這個記錄裡可以說明一下登入的使用者是誰,然後把這條記錄的 ID 號傳送給客戶端,客戶端收到以後把這個 ID 號儲存在 Cookie 裡,下次這個使用者再向服務端傳送請求的時候,可以帶著這個 Cookie ,這樣服務端會驗證一個這個 Cookie 裡的資訊,看看能不能在服務端這裡找到對應的記錄,如果可以,說明使用者已經通過了身份驗證,就把使用者請求的資料返回給客戶端。
    上面說的就是 Session,我們需要在服務端儲存為登入的使用者生成的 Session ,這些 Session 可能會儲存在記憶體,磁碟,或者資料庫裡。我們可能需要在服務端定期的去清理過期的 Session 。

JWT的身份驗證:

使用基於 Token 的身份驗證方法,在服務端不需要儲存使用者的登入記錄。大概的流程是這樣的:
1、客戶端使用使用者名稱跟密碼請求登入
2、 服務端收到請求,去驗證使用者名稱與密碼
3、驗證成功後,服務端會簽發一個 Token,再把這個 Token 傳送給客戶端
4、客戶端收到 Token 以後可以把它儲存起來,比如放在 Cookie 裡或者 Local Storage 裡
5、客戶端每次向服務端請求資源的時候需要帶著服務端簽發的 Token
6、服務端收到請求,然後去驗證客戶端請求裡面帶著的 Token,如果驗證成功,就向客戶端返回請求的資料

2、JWT的token組成

    實施 Token 驗證的方法挺多的,還有一些標準方法,比如 JWT,讀作:jot ,表示:JSON Web Tokens 。JWT 標準的 Token 有三個部分:
    header(頭部)
    payload(資料)
    signature(簽名)
    中間用點分隔開,並且都會使用 Base64 編碼,所以真正的 Token 看起來像這樣:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

頭部:

每個 JWT token 裡面都有一個 header,也就是頭部資料。裡面包含了使用的演算法,這個 JWT 是不是帶簽名的或者加密的。主要就是說明一下怎麼處理這個 JWT token 。

頭部裡包含的東西可能會根據 JWT 的型別有所變化,比如一個加密的 JWT 裡面要包含使用的加密的演算法。唯一在頭部裡面要包含的是 alg 這個屬性,如果是加密的 JWT,這個屬性的值就是使用的簽名或者解密用的演算法。如果是未加密的 JWT,這個屬性的值要設定成 none

示例:


1.png

意思是這個 JWT 用的演算法是 HS256。上面的內容得用 base64url 的形式編碼一下,所以就變成這樣:

2.png

Payload:

Payload 裡面是 Token 的具體內容,這些內容裡面有一些是標準欄位,你也可以新增其它需要的內容。下面是標準欄位:

iss:Issuer,發行者
sub:Subject,主題
aud:Audience,觀眾
exp:Expiration time,過期時間
nbf:Not before
iat:Issued at,發行時間
jti:JWT ID
比如下面這個 Payload ,用到了 iss 發行人,還有 exp 過期時間這兩個標準欄位。另外還有兩個自定義的欄位,一個是 name ,還有一個是 admin 。


3.png

使用 base64url 編碼以後就變成了這個樣子:


4.png

Signature:

JWT 的最後一部分是 Signature ,這部分內容有三個部分,先是用 Base64 編碼的 header.payload ,再用加密演算法加密一下,加密的時候要放進去一個 Secret ,這個相當於是一個密碼,這個密碼祕密地儲存在服務端。

header
payload
secret


5.png

處理完成以後看起來像這樣:


6.png
最後這個在服務端生成並且要傳送給客戶端的 Token 看起來像這樣:
7.png
客戶端收到這個 Token 以後把它儲存下來,下回向服務端傳送請求的時候就帶著這個 Token 。服務端收到這個 Token ,然後進行驗證,通過以後就會返回給客戶端想要的資源。

3、簽發和驗證JWT的功能

在應用裡實施使用基於 JWT 這種 Token 的身份驗證方法,你可以先去找一個簽發與驗證 JWT 的功能包。無論你的後端應用使用的是什麼樣的程式語言,系統,或者框架,你應該都可以找到提供類似功能的包。
下面我們在一個 Node.js 專案裡,用最簡單的方式來演示一下籤發還有驗證 JWT 的方法。練習有個視訊版本,你可以參考《 JWT:JSON Web Token 》這個免費的視訊課程。

專案程式碼https://github.com/ninghao/jwt-demo

準備專案

準備一個簡單的 Node.js 專案:
下面我們在一個 Node.js 專案裡,用最簡單的方式來演示一下籤發還有驗證 JWT 的方法。練習有個視訊版本,你可以參考《 JWT:JSON Web Token 》這個免費的視訊課程。

專案程式碼https://github.com/ninghao/jwt-demo

準備專案

準備一個簡單的 Node.js 專案:

8.png
安裝簽發與驗證 JWT 的功能包,我用的叫 jsonwebtoken,在專案裡安裝一下這個包:
9.png

簽發 JWT

在專案裡隨便新增一個 .js 檔案,比如 index.js,在檔案裡新增下面這些程式碼:


10.png

非常簡單,就是用了剛剛為專案安裝的 jsonwebtoken 裡面提供的 jwt.sign 功能,去簽發一個 token。這個 sign 方法需要三個引數:

playload:簽發的 token 裡面要包含的一些資料。
secret:簽發 token 用的金鑰,在驗證 token 的時候同樣需要用到這個金鑰。
options:一些其它的選項。
在命令列下面,用 node 命令,執行一下專案裡的 index.js 這個檔案(node index.js),會輸出應用簽發的 token:


11.png

上面的 Token 內容並沒有加密,所以如果用一些 JWT 解碼功能,可以看到 Token 裡面包含的內容,內容由三個部分組成,像這樣:


12.png
假設使用者通過了某種身份驗證,你就可以使用上面的簽發 Token 的功能為使用者簽發一個 Token。一般在客戶端那裡會把它儲存在 Cookie 或 LocalStorage 裡面。

使用者下次向我們的應用請求受保護的資源的時候,可以在請求裡帶著我們給它簽發的這個 Token,後端應用收到請求,檢查簽名,如果驗證通過確定這個 Token 是我們自己簽發的,那就可以為使用者響應回他需要的資源。

驗證 JWT

驗證 JWT 的用效性,確定一下使用者的 JWT 是我們自己簽發的,首先要得到使用者的這個 JWT Token,然後用 jwt.verify 這個方法去做一下驗證。這個方法是 Node.js 的 jsonwebtoken 這個包裡提供的,在其它的應用框架或者系統裡,你可能會找到類似的方法來驗證 JWT。

開啟專案的 index.js 檔案,裡面新增幾行程式碼:


13.png

把要驗證的 Token 資料,還有簽發這個 Token 的時候用的那個金鑰告訴 verify 這個方法,在一個回撥裡面有兩個引數,error 表示錯誤,decoded 是解碼之後的 Token 資料。

執行:


14.png

輸出:


15.png
注意輸出了一個 invalid signature ,表示 Token 裡的簽名不對,這是因為我們組長 verify 方法提供的金鑰並不是簽發 Token 的時候用的那個金鑰。這樣修改一下:
16.png

再次執行,會輸出類似的資料:


17.png

RS256 演算法

預設簽發還有驗證 Token 的時候用的是 HS256 演算法,這種演算法需要一個金鑰(密碼)。我們還可以使用 RS256 演算法簽發與驗證 JWT。這種方法可以讓我們分離開簽發與驗證,簽發時需要用一個金鑰,驗證時使用公鑰,也就是有公鑰的地方只能做驗證,但不能簽發 JWT。

在專案下面建立一個新的目錄,裡面可以儲存即將生成的金鑰與公鑰檔案。


18.png

金鑰

先生成一個金鑰檔案:


19.png

公鑰

基於上面生成的金鑰,再去建立一個對應的公鑰:


20.png

簽發 JWT(RS256 演算法)

用 RS256 演算法簽發 JWT 的時候,需要從檔案系統上讀取建立的金鑰檔案裡的內容。


21.png

簽發仍然使用 jwt.sign 方法,只不過在選項引數裡特別說明一下使用的演算法是 RS256:


22.png

驗證 JWT(RS256 演算法)

驗證使用 RS256 演算法簽發的 JWT,需要在檔案系統上讀取公鑰檔案裡的內容。然後用 jwt 的 verify 方法去做驗證。


23.png

相關課程

  1. JWT:JSON Web Token
  2. Node.js:基於 Token 的身份驗證
  3. WordPress 開發:身份驗證(JWT)》
  4. 微信小程式:應用後臺__身份驗證 #3

感謝原創,如有侵權,可聯絡本人刪除。

      </div>
    </div>