python 实现JWT


[TOC]

python 生成JWT 规范Token

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信息。

JWT 含义 :JSON 格式的在web 中传输的Token(令牌),既然是Token那一定是加密过得

JWT 实现:

JWT 有两种实现方式JWS(JSON Web Signature)以及JWE(JSON Web Encryption)

目前很多实现JWT是 JWS和自加密

JWT 优势:

安全并且轻量

JWT 应用:

Token签证

JSON Web Signature(JWS)

JSON Web Signature是一个有着简单的统一表达形式的字符串:

结构分为三段由 . 隔开传输时长这样

eyJhbGciOiJIUzUxMiIsImlhdCI6MTYwMjU1NzU0NCwiZXhwIjoxOTE3OTE3NTQ0fQ.eyJ1aWQiOiJhMTkzYjllN2E2YWY3YTA2MzkwIn0.XgQJEfniX6bbMNMMr2CTtY4wcYbJFAGsNV8dBecoN2mxGN3c_uawWjdE7ZXTBh_5vozczokwz2HQj_6y6ahyVA

解析后的三段

头部(Header) 头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。 JSON内容要经Base64 编码生成字符串成为Header。

载荷(PayLoad) payload的五个字段都是由JWT的标准所定义的。

iss: 该JWT的签发者 sub: 该JWT所面向的用户 aud: 接收该JWT的一方 exp(expires): 什么时候过期,这里是一个Unix时间戳 iat(issued at): 在什么时候签发的 后面的信息可以按需补充。 JSON内容要经Base64 编码生成字符串成为PayLoad。

签名(signature) 这个部分header与payload通过header中声明的加密方式,使用密钥secret进行加密,生成签名。 JWS的主要目的是保证了数据在传输过程中不被修改,验证数据的完整性。但由于仅采用Base64对消息内容编码,因此不保证数据的不可泄露性。所以不适合用于传输敏感数据。

头部 和 载荷 部分仅仅是base64 编码的,前端或任意人都可以解码出来(所以也可以加密后再传输)

签名 部分是加密过得用来校验的

JSON Web Encryption(JWE)

相对于JWS,JWE则同时保证了安全性与数据完整性。 JWE由五部分组成 也是 . 隔开:

1 JOSE含义与JWS头部相同。

2 生成一个随机的Content Encryption Key (CEK)。

3 使用RSAES-OAEP 加密算法,用公钥加密CEK,生成JWE Encrypted Key。

4 生成JWE初始化向量。

5 使用AES GCM加密算法对明文部分进行加密生成密文Ciphertext,算法会随之生成一个128位的认证标记Authentication Tag。

最后对五个部分分别进行base64编码

可见,JWE的计算过程相对繁琐,不够轻量级,因此适合与数据传输而非token认证,但该协议也足够安全可靠,用简短字符串描述了传输内容,兼顾数据的安全性与完整性。

如果是为了传输数据也有其他加密传输方式故JWE应用并不如JWS

python实现JWS

登录可用检验 token 可用内置模块

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

secret_key = "这是秘钥"
# 生成token
def create_token(uid):
    '''
    :param uid:用户id
    :return: token
    '''

    # 第一个参数是内部的私钥
    # 第二个参数是有效期(秒)
    s = Serializer(secret_key,
                   expires_in=2592000)
    # 接收用户id转换与编码
    token = s.dumps({"uid": uid,"name":name,"other":other}).decode("ascii")
    return token

# 校验token
def verify_token(token):
    '''

    :param token:
    :return: 用户信息 or None
    '''

    # 参数为私有秘钥,跟上面方法的秘钥保持一致
    s = Serializer(config.token["secret_key"])
    try:
        # 校验signature解析payload,header
        payload,header = s.loads(token,return_header=True)
    except Exception:
        return (错误JWT)

    return payload

一个小细节,在不同系统中生成的token 可能无法通过校验,可能和编码有关