python實現JWT
一、常見的幾種實現認證的方法
1.1basic auth
1.2cookie
1.3token
json web token--一種基於token的json格式web認證方法。基本原理是,第一次認證通過用戶名和面膜,服務端簽發一個json格式的token,后續客戶端的請求都帶着這個token,服務端僅需要解析這個token,來判斷客戶端的身份和合法性。jwt協議只是規范了這個協議的格式,分為三個部分
1.3.1header頭部
{ 'type':'JWT', #聲名類型,這里是JWT 'alg':'HS256' #聲名加密的算法,通常為 HMAC SHA256 }
再將其解析base64編碼
1.3.2payload載荷
payload是放置實際有效信息的地方。jwt定義了幾種內容,包括: 標准中注冊的聲明,如簽發者,接收者,有效時間(exp),時間戳(iat,issued at)等;為官方建議但非必須 公共聲明 私有聲明
#一個常見的payload { 'user_id':12345, 'user_role':admin, 'iat':14234234 }
// 包括需要傳遞的用戶信息; { "iss": "Online JWT Builder", #該JWT的簽發者,是否使用是可選的; "iat": 1416797419, #在什么時候簽發的(UNIX時間),是否使用是可選的; "exp": 1448333419, #什么時候過期,這里是一個Unix時間戳,是否使用是可選的; "aud": "www.gusibi.com", #接收該JWT的一方,是否使用是可選的; "sub": "uid", #該JWT所面向的用戶,是否使用是可選的; "nickname": "goodspeed", "username": "goodspeed", "scopes": [ "admin", "user" ] }
1.3.3signature
原理
// 根據alg算法與私有秘鑰進行加密得到的簽名字串; // 這一段是最重要的敏感信息,只能在服務端解密; HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), SECREATE_KEY )
第三部分是個簽證信息,有三部分組成:
header(base64后的)
payload(base64后的)
secret
存儲了序列化的secreate key和salt key。這個部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,
然后通過header中聲明的加密方式進行加鹽secret組合加密,然后就構成了jwt的第三部分。
示例圖:
二、認證需求
目標場景是一個前后端分離的后端系統,用於運維工作,雖在內網使用,也有一定的保密性要求 API為restful+json的無狀態接口,要求認證也是相同模式 可橫向擴展 較低數據庫壓力 證書可注銷 證書可自動延期 這樣就選擇JWT
三、JWT實現
如何生成token

import jwt import time # 使用 sanic 作為restful api 框架 def create_token(request): grant_type = request.json.get('grant_type') username = request.json['username'] password = request.json['password'] if grant_type == 'password': account = verify_password(username, password) elif grant_type == 'wxapp': account = verify_wxapp(username, password) if not account: return {} payload = { "iss": "gusibi.com", "iat": int(time.time()), "exp": int(time.time()) + 86400 * 7, "aud": "www.gusibi.com", "sub": account['_id'], "username": account['username'], "scopes": ['open'] } token = jwt.encode(payload, 'secret', algorithm='HS256') return True, {'access_token': token, 'account_id': account['_id']} def verify_bearer_token(token): # 如果在生成token的時候使用了aud參數,那么校驗的時候也需要添加此參數 payload = jwt.decode(token, 'secret', audience='www.gusibi.com', algorithms=['HS256']) if payload: return True, token return False, token
如何解析token
四、優化
總結
我們做了一個JWT的認證模塊: (access token在以下代碼中為'token',refresh token在代碼中為'rftoken') 首次認證 client -----用戶名密碼-----------> server client <------token、rftoken----- server access token存續期內的請求 client ------請求(攜帶token)----> server client <-----結果----------------- server access token超時 client ------請求(攜帶token)----> server client <-----msg:token expired--- server 重新申請access token client -請求新token(攜帶rftoken)-> server client <-----新token-------------- server rftoken token超時 client -請求新token(攜帶rftoken)-> server client <----msg:rftoken expired--- server 如果設計一個針對此認證的前端,需要: 存儲access token、refresh token 訪問時攜帶access token,自動檢查access token超時,超時則使用refresh token更新access token;狀態延期用戶無感知 用戶登出直接拋棄access token與refresh token