python實現JWT


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
View Code

 

如何解析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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM