最近要用 Falsk 開發一個大點的后端,為了安全考慮,棄用傳統的Cookie驗證。轉用JWT。
其實 Falsk 有一個 Falsk-JWT 但是我覺得封裝的太高,還是喜歡通用的 PyJWT 。
JWT官網
https://jwt.io/
安裝
pip install PyJWT
項目文檔(英文)
https://pyjwt.readthedocs.io/en/latest/
Demo
import jwt import datetime dic = { 'exp': datetime.datetime.now() + datetime.timedelta(days=1), # 過期時間 'iat': datetime.datetime.now(), # 開始時間 'iss': 'lianzong', # 簽名 'data': { # 內容,一般存放該用戶id和開始時間 'a': 1, 'b': 2, }, } s = jwt.encode(dic, 'secret', algorithm='HS256') # 加密生成字符串 print(s) s = jwt.decode(s, 'secret', issuer='lianzong', algorithms=['HS256']) # 解密,校驗簽名 print(s) print(type(s))
結果
b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDUzMDI5OTIsImlhdCI6MTU0NTIxNjU5MiwiaXNzIjoibGlhbnpvbmciLCJkYXRhIjp7ImEiOjEsImIiOjJ9fQ.pSq-XRcC-E7zeg3u0X6TsKdhhsCPh3tB40_YJNho8CY' {'exp': 1545302992, 'iat': 1545216592, 'iss': 'lianzong', 'data': {'a': 1, 'b': 2}} <class 'dict'>
解析
首先我們注意dic的結構
dic 有官方指定的key,程序在解密的時候會根據key的Value判斷是否合法。這些key有
- “exp”: 過期時間
- “nbf”: 表示當前時間在nbf里的時間之前,則Token不被接受
- “iss”: token簽發者
- “aud”: 接收者
- “iat”: 發行時間
我們一般設置 過期時間,發行時間,接收者。我們來分別解釋這些key
exp
exp指過期時間,在生成token時,可以設置該token的有效時間,如果我們設置1天過期,1天后我們再解析此token會拋出
jwt.exceptions.ExpiredSignatureError: Signature has expired
nbf
nbf類似於token的 lat ,它指的是該token的生效時間,如果使用但是沒到生效時間則拋出
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)
iss
iss指的是該token的簽發者,我們可以給他一個字符串。
注意,iss 在接收時如果不檢驗也沒有問題,如果我們接收時需要檢驗但是又簽名不一致,則會拋出
jwt.exceptions.InvalidIssuerError: Invalid issuer
aud
aud指定了接收者,接收者在接收時必須提供與token要求的一致的接收者(字符串),如果沒寫接收者或者接收者不一致會拋出
jwt.exceptions.InvalidAudienceError: Invalid audience
iat
iat指的是token的開始時間,如果當前時間在開始時間之前則拋出
jwt.exceptions.InvalidIssuedAtError: Issued At claim (iat) cannot be in the future.
注意
如果我們不需要驗證所有信息直接生成token可以設置
jwt.decode(encoded, verify=False)
但是這樣有什么用呢?
生成/解密參數
jwt.encode(payload, config.SECRET_KEY, algorithm='HS256')
上面代碼的jwt.encode方法中傳入了三個參數:第一個是payload,這是認證依據的主要信息,第二個是密鑰,這里是讀取配置文件中的SECRET_KEY配置變量,第三個是生成Token的算法。
一般我們使用HS256
第二個參數是生成token的密鑰
我們需要在加密時指定
解密時也是第二個參數來指定解密密鑰,這兩個密鑰必須相同
