天天看點

Python 使用rsa類庫基于RSA256算法生成JWT

JWT

簡介

JWT

(Json web token)

,是為了在網絡應用環境間傳遞聲明而執行的一種基于JSON的開放标準。JWT提供了一種簡單、安全的身份認證方法,特别适合分布式站點單點登入、或者是簽名。

JWT構成

JWT是由3部分資訊組成,分别為

header

payload

signature

,組合形式為:

header.payload.signature

(注意:這裡的

header

payload

signature

都是經過base64加密的值)

header

格式如下:

{
  'typ': 'JWT', # 聲明類型
  'alg': 'RS256' # 聲明加密算法 # RSA Signature withSHA-256
}
           

要構成

JWT

組成部分之前,需要對其進行

base64

加密,得到一字元串,形如:

eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiJ9

payload

payload

用于存放有效資訊,可劃分為三部分。

  • 标準聲明
  • 公共聲明
  • 私有聲明

标準聲明(建議但不強制使用)

  • iss

    :issue,

    JWT

    簽發者
  • sub

    :subject,主題
  • aud

    :audience,閱聽人,該JWT所面向的使用者
  • exp

    JWT

    過期時間戳,機關秒,這個過期時間必須要大于簽發時間
  • nbf

    :定義在什麼時間之前,該

    JWT

    都是不可用的
  • iat

    JWT

    簽發時間
  • jti

    JWT

    的唯一身份辨別,主要用來作為一次性

    token

    ,進而避免重播攻擊。

公共聲明可以添加任何的資訊,一般添加使用者的相關資訊或其他業務需要的必要資訊。一般不建議添加敏感資訊,因為該部分在用戶端可解密。

私有聲明是提供者和消費者所共同定義的聲明,一般不建議添加敏感資訊,因為該部分在用戶端也是可解密。

格式如下

{
    "iss":"shouke", 
    "sub":"test_subject",  
    "aud":"tester",    
    "iat":1624499492,
    "exp":1624535491, 
    "jti":"8NLazrgnXpAvmHA6eybETH7RT8sUWbag",   
    "username":"shouke",
    "hobby":"unknow"
}
           

header

一樣,要構成

JWT

base64

eyJpc3MiOiAiY2Fzc21hbGwuY29tIiwgInN1YiI6ICJtYW5keSIsICJhdWQiOiAiY2Fzc21hbGwiLCAiaWF0IjogMTYyNTI4NzIzNSwgImV4cCI6IDE2NTY4MjMyMzUsICJqdGkiOiAiSmVRbUxqUlpaR0hjVEh1ZE5FdWRiUyIsICJ1c2VybmFtZSI6ICJzaG91a2UiLCAiaG9iYnkiOiAidW5rbm93In0=
           

signature

header

payload

構成了

signature

基礎資訊,格式為:

header.payload

,其中

header

payload

,也是

base64

加密後的值。

L1THOR4+gsksnDzwjGDsVCjvwlO7NBRdC6cVHAy1pycUGBugE6UM6mj/So1QRivVOyzk/OafHg9KpsR3/93SJ4SJXIyYhLaJXfIH+6tvi9Z72h6A2ko2AT//gfdtAtTJEMAF8rlsuu58FgYSQn2GjCIgn8oRNyX5S4w5Zmz+cJk=
           
eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiJ9.eyJpc3MiOiAiY2Fzc21hbGwuY29tIiwgInN1YiI6ICJtYW5keSIsICJhdWQiOiAiY2Fzc21hbGwiLCAiaWF0IjogMTYyNTI4NzIzNSwgImV4cCI6IDE2NTY4MjMyMzUsICJqdGkiOiAiSmVRbUxqUlpaR0hjVEh1ZE5FdWRiUyIsICJ1c2VybmFtZSI6ICJzaG91a2UiLCAiaG9iYnkiOiAidW5rbm93In0=.L1THOR4+gsksnDzwjGDsVCjvwlO7NBRdC6cVHAy1pycUGBugE6UM6mj/So1QRivVOyzk/OafHg9KpsR3/93SJ4SJXIyYhLaJXfIH+6tvi9Z72h6A2ko2AT//gfdtAtTJEMAF8rlsuu58FgYSQn2GjCIgn8oRNyX5S4w5Zmz+cJk=
           

代碼實作

import rsa

import base64
import json
import shortuuid
from datetime import datetime, timedelta
def make_jwt():
    header = { 'typ': 'JWT',  # 令牌類型
               'alg': 'RS256' # 使用的算法 # RSA Signature withSHA-256
             }

    header = base64.b64encode(json.dumps(header).encode()).decode() # encode  decode 預設使用utf-8
    print(header)
    payload = {
        "iss":"cassmall.com",
        "sub":"mandy",
        "aud":"cassmall",
        "iat":int(datetime.now().timestamp()),
        "exp":int((datetime.now()+ timedelta(seconds=31536000)).timestamp()), # JWT過期時間戳,機關秒
        "jti":shortuuid.uuid(),
        "username":"shouke",
        "hobby":"unknow"
    }
    payload = base64.b64encode(json.dumps(payload).encode()).decode()
    print(payload)
    signature = genrate_signature(1024, '{header}.{payload}'.format(header=header, payload=payload).encode('utf-8'), 'SHA-256')
    print(signature)

    return '{header}.{payload}.{signature}'.format(header=header,
                                                      payload=payload,
                                                      signature=signature)


def genrate_signature(nbits, message, hash_method):
    (pubkey, privkey) = rsa.newkeys(nbits)
    if not isinstance(message, bytes):
        message = message.encode('utf-8')
    hash = rsa.compute_hash(message, hash_method)
    return base64.b64encode(rsa.sign(hash, privkey, hash_method)).decode()


if __name__ == '__main__':
    print(make_jwt())