JSON Web Tokens 系统用户认证 jwt

一种开发的行业标准 RFC 7519 ,用于安全的表示双方之间的声明。
广泛应用在系统的用户认证

浏览器发送 用户名和密码 到服务器中,服务端判断用户名和密码是否正确,
如果正确则生成一个 token,并返回给浏览器

浏览器每次都要带有服务端返回的 token ,一起进行请求,
由服务端校验 token 的合法性
如果合法则返回数据,不合法则返回浏览器错误信息

jwt 生成 token 的示例如下(总共为三段字符串,使用 . 进行分隔)
eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.
eyJ1c2VyX2lkIjoxMTExLCJ1c2VybmFtZSI6IkhhbnkiLCJleHAiOjE2MDI3MjQxMTZ9.
-ivPhXGKYAn7ON0rMInChUBHMjiBOtvthHhdwcxvkRY

第一段字符串表示为
eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.
是 HEADER 部分,固定包含算法和 token 类型,
对 json 进行 base64url 加密

    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }

第二段字符串表示为
eyJ1c2VyX2lkIjoxMTExLCJ1c2VybmFtZSI6IkhhbnkiLCJleHAiOjE2MDI3MjQxMTZ9.
是 payload 部分,包含有一部分数据,对 json 进行 base64url 加密

    payload = {
        'user_id': 1111, # 自定义用户ID
        'username': 'Hany', # 自定义用户名
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5) # 超时时间
    }

第三段字符串表示为
-ivPhXGKYAn7ON0rMInChUBHMjiBOtvthHhdwcxvkRY
将前两段字符串的密文通过 . 进行拼接起来,然后使用 HS256 进行加密,
对 HS256 密文进行 base64url 加密,得到 token 的第三段

    base64url(
        HMACSHA256(
          base64UrlEncode(header) + "." + base64UrlEncode(payload),
          your-256-bit-secret (秘钥加盐)
        )
    )

替换规则:
base64url 加密是先做 base64 加密,然后再将 - 替代 + , _ 替代 /

关于 jwt 的安装
pip install jwt

基于 Python 的 pyjwt 实现代码:

import jwt
import datetime
SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='

def create_token():
    # 构造header
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }
    # 构造payload
    payload = {
        'user_id': 1111, # 自定义用户ID
        'username': 'Hany', # 自定义用户名
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5) # 超时时间
    }
    result = jwt.encode(payload = payload, key = SALT, algorithm = "HS256", headers = headers).decode('utf-8')
    return result

if __name__ == '__main__':
    token = create_token()
    print(token)

浏览器 会携带服务器端返回的 token 进行 超时 及 合法性 校验
服务器端在获取到用户携带的 token 后,会对 token 解密为三个字符串
即 header_segment , payload_segment , crypto_segment 三部分
然后对 header_segment , payload_segment , crypto_segment 进行 base64url 解密,
得到 header , payload , signature 三部分
服务器端会对 signature 这一部分进行合法性校验

校验规则如下:
    jwt 生成 token 的前两段字符(第二个 . 之前的所有字符),
        即 对 HEADER 和 payload 进行 base64url 加密后产生的字符串
    (从第一段明文中)获取加密算法,默认 HS256
    使用 算法 + 盐 对 token 的前两段字符进行加密,将得到的结果与第三段 signature 密文进行比较

实现代码:

import jwt
from jwt import exceptions
def get_payload(token):
    try:
        SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
        verified_payload = jwt.decode(token, SALT, True)
        print("token 认证成功")
        return verified_payload
    except exceptions.ExpiredSignatureError:
        print('token 已失效')
    except jwt.DecodeError:
        print('token 认证失败')
    except jwt.InvalidTokenError:
        print('非法的 token')
        
if __name__ == '__main__':
    token = "eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMTExLCJ1c2VybmFtZSI6IkhhbnkiLCJleHAiOjE2MDI3MjY1MjN9.r49ST_8v71BswEkvOSGjyGWY5J6ksmz8BCAhZNxjgOg"
    payload = get_payload(token)


注: token 可以先自己手动生成一份,然后再进行复制粘贴到此代码中,进行 jwt 的用户认证

参考链接:

https://www.pythonav.com/wiki/detail/6/67/

2020-10-15

原文地址:https://www.cnblogs.com/hany-postq473111315/p/13818871.html