欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 使用rsa类库基于RSA256算法生成JWT

程序员文章站 2022-03-01 20:28:27
JWT简介 JWT(Json web token),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT提供了一种简单、安全的身份认证方法,特别适合分布式站点单点登录、或者是签名。 JWT构成 JWT是由3部分信息组成,分别为header,payload,signature,组合 ......

jwt简介

jwt(json web token),是为了在网络应用环境间传递声明而执行的一种基于json的开放标准。jwt提供了一种简单、安全的身份认证方法,特别适合分布式站点单点登录、或者是签名。

jwt构成

jwt是由3部分信息组成,分别为headerpayloadsignature,组合形式为:header.payload.signature(注意:这里的headerpayloadsignature都是经过base64加密的值)

格式如下:

{
  '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都是不可用的

  • iatjwt签发时间

  • jtijwt的唯一身份标识,主要用来作为一次性token,从而避免重放攻击。

公共声明

公共声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。一般不建议添加敏感信息,因为该部分在客户端可解密。

私有声明

私有声明是提供者和消费者所共同定义的声明,一般不建议添加敏感信息,因为该部分在客户端也是可解密。

格式如下

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

header一样,要构成jwt组成部分之前,需要对其进行base64加密,得到一字符串,形如:

eyjpc3mioiaiy2fzc21hbgwuy29tiiwginn1yii6icjtyw5kesisicjhdwqioiaiy2fzc21hbgwilcaiawf0ijogmtyynti4nziznswgimv4cci6ide2nty4mjmymzusicjqdgkioiaismvrbuxqulpar0hjveh1ze5fdwriuyisicj1c2vybmftzsi6icjzag91a2uilcaiag9iynkioiaidw5rbm93in0=

signature

headerpayload构成了signature基础信息,格式为:header.payload,其中headerpayload,也是base64加密后的值。

构成jwt组成部分之前,需要采用headeralg配置对应的算法,对上述基础信息进行加密,然后对加密结果进行base64编码,得到最终的signature

l1thor4+gsksndzwjgdsvcjvwlo7nbrdc6cvhay1pycugbuge6um6mj/so1qrivvoyzk/oafhg9kpsr3/93sj4sjxiyyhlajxfih+6tvi9z72h6a2ko2at//gfdtattjemaf8rlsuu58fgysqn2gjcign8ornyx5s4w5zmz+cjk=

最后,将以上三部分用.连接起来,得到jwt,如下

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())