Skip to content

01. JWT详解与LLMOps授权流程 ​

JWT 是一种服务端向客户端发送令牌的认证方式。当客户端使用用户名和密码登录时,服务端会生成一个包含用户信息的 JWT 令牌,并将其返回给客户端。客户端在后续的请求中只需携带这个令牌,服务端通过验证令牌来确认用户身份,从而实现对用户的身份验证和授权。 整体的授权流程如下

JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。1.头部(Header):头部描述了 JWT 的元数据,包含算法(alg)和类别(typ)等信息。2.载荷(Payload):载荷包含了用户信息和其他元数据,这些信息可以是用户的名字、角色、到期时间等。载荷是 JWT 的主体部分,用于传递用户信息。3.签名(Signature):签名用于验证 JWT 的完整性和真实性,签名通过对头部和载荷进行哈希运算,并使用私钥进行加密生成。接收者可以使用公钥对签名进行解密,从而验证 JWT 的真实性和来源。 例如以下是一个 JWT 示例 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c 其中 头部 和 载荷 是非加密的,可以使用 base64 进行解码,例如上述的信息解码后如下 头部:{"alg":"HS256","typ":"JWT"} 载荷:

在 载荷 中一般有几个标准数据: 1.iss:Issuer,表示 JWT 的签发者。 2.sub:Subject,代表 JWT 的主体,通常是用户的唯一标识符。 3.exp:Expiration Time,表示 JWT 的过期时间,类型为时间戳,单位为秒。 4.iat:Issued At,表示 JWT 的签发时间,类型为时间戳,单位为秒。 5.aud:Audience,表示 JWT 的接收方,例如应用的 ID 或域名,用于限制 JWT 的接受范围。 在 Python 中使用 JWT 也非常简单,通过以下命令快捷安装

bash
pip install PyJWT

接下来就可以使用 PyJWT 提供的工具快速生成或者解析 access_token ,示例如下

python
import os
import jwt

def generate_token(payload: dict[str, Any]) -> str:
    """将传入的载荷生成相应的token"""
    secret_key = os.getenv("JWT_SECRET_KEY")
    return jwt.encode(payload, secret_key, algorithm="HS256")

def parse_token(token: str) -> dict[str, Any]:
    """解析传入的token信息"""
    secret_key = os.getenv("JWT_SECRET_KEY")
    return jwt.decode(token, secret_key, algorithms=["HS256"])

对于 JWT 的秘钥来说,最好使用 较长且复杂的字符串,比如生成一个 32 字节或者更长的随机字符串,在 Windows 下可以通过以下命令随机生成一个长度为 32 位的字符串(代码由 ChatGPT 生成)

bash
powershell -Command "( -join (Get-Random -Count 32 -InputObject (48..57 + 65..90 + 97..122 | ForEach-Object {[char]$_})))"

02. 哈希加密 ​

哈希加密是一种不可逆的加密算法,用于将任意长度的输入通过算法转换为固定长度的输出,常用于密码存储、数据完整性校验等。哈希加密的特点也非常明显:1.不可逆:无法从哈希值直接还原原始数据。2.抗碰撞:不同的输入很难产生相同的哈希值。3.快速计算:适合大数据集的快速计算。 常见的哈希算法有:MD5、SHA-1、SHA-256 等。 在课程中,不会存储用户的密码原文,而是随机生成一个 salt(盐值),利用 salt+password 实现哈希计算,在数据库中存储 加密后的密码,在需要进行比较时,使用 输入密码+salt 进行哈希加密计算,利用计算得到的数据和 存储的加密密码 进行比较,从而完成对数据的校验。 在 Python 中对应的封装代码如下

python
import base64
import binascii
import hashlib
import re
from typing import Any

# 密码校验正则,密码最少包含一个字母、一个数字、并且长度为8-16
password_pattern = r"^(?=.*[a-zA-Z])(?=.*\d).{8,16}$"


def validate_password(password: str, pattern: str = password_pattern):
    """校验传入的密码是否符合相应的匹配规则"""
    if re.match(pattern, password) is None:
        raise ValueError("密码规则校验失败,至少包含一个字母,一个数字,并且长度为8-16位")
    return


def hash_password(password: str, salt: Any) -> bytes:
    """将传入的密码+盐值进行哈希加密"""
    dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, 10000)
    return binascii.hexlify(dk)


def compare_password(password: str, password_hashed_base64: Any, salt_base64: Any) -> bool:
    """根据传入的密码+盐值校验对比是否一致"""
    return hash_password(password, base64.b64decode(salt_base64)) == base64.b64decode(password_hashed_base64)

总结 ​

  1. JWT由Header、Payload、Signature三部分组成,Payload包含iss、sub、exp等标准字段,可通过PyJWT库快速生成和解析,秘钥建议使用32字节以上的随机字符串。
  2. 哈希加密具有不可逆、抗碰撞、计算快的特点,密码存储时结合salt+password做哈希计算,通过对比哈希值完成密码校验,常用算法为SHA-256。
  3. 密码校验需满足正则规则:至少包含一个字母、一个数字,长度8-16位,保障密码复杂度。

Talk is cheap, show me the code!