Python JWT 原理、校验与 PyJWT 实战详解

小石头
小石头
发布时间:2026-10-15 | 3人浏览过
原创

本文详解 JWT(JSON Web Tokens)在前后端分离架构中的认证流程,对比传统 Token 与 JWT 的差异。深入解析 JWT 生成与校验的三段式结构及 Base64URL 编码原理,并结合 Python 的 PyJWT 库展示代码实现。重点介绍 exp、nbf、iss、aud、iat 等关键参数的配置与异常处理,帮助开发者安全高效地实现用户身份验证。

1. JWT 介绍

JWT(JSON Web Tokens)是一项开放的行业标准(RFC 7519),旨在安全地表示双方之间的声明。目前,JWT 已广泛应用于系统用户认证场景,特别是在前后端分离的项目架构中。

在典型的项目开发流程中,认证过程遵循特定步骤:用户登录成功后,服务端向浏览器返回一个 token。此后,浏览器在发起请求时需携带该 token,服务端对 token 进行合法性校验。若校验通过,则返回数据;否则返回错误信息。

传统 Token 方式与 JWT 在认证机制上存在显著差异。

  • 传统 token 方式:用户登录成功后,服务端生成一个随机 token 返回给用户,并在服务端(数据库或缓存)中保存一份副本。后续用户访问时需携带该 token,服务端接收后去数据库或缓存中校验其是否超时及合法。
  • jwt 方式:用户登录成功后,服务端通过 JWT 生成一个随机 token 返回给用户(服务端无需保存该 token)。后续用户访问时携带 token,服务端接收后直接通过 JWT 机制校验其是否超时及合法。

2. JWT 创建 token

2.1 JWT 生成原理

JWT 生成的 token 格式由点号(.)连接的三段字符串组成。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

其生成规则如下:

第一段 HEADER 部分,固定包含算法和 token 类型。对该 JSON 进行 base64url 编码处理后,即得到 token 的第一段。


{
"alg": "HS256",
"typ": "JWT"
}

第二段 PAYLOAD 部分,包含具体的业务数据。对该 JSON 进行 base64url 编码处理后,即得到 token 的第二段。


{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
...
}

第三段 SIGNATURE 部分,将前两段的 base64url 编码结果通过点号(.)拼接,然后使用 HS256 算法进行加密,最后对加密结果再进行 base64url 编码,最终得到 token 的第三段。


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

最后,将这三段字符串通过点号(.)拼接起来,便生成了完整的 JWT token。

注意:base64url 编码是在标准 base64 编码基础上,将加号(+)替换为减号(-),将斜杠(/)替换为下划线(_)。

2.2 JWT 校验 token 原理

通常在认证成功后将 JWT 生成的 token 返回给用户。当用户再次访问时,需携带该 token,此时 JWT 机制会对 token 进行超时及合法性校验。获取 token 后,校验步骤如下:

将 token 分割为 header_segment、payload_segment、crypto_segment 三部分。


JWT_TOKEN =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

signing_input, crypto_segment = JWT_TOKEN.rsplit('.', 1)
header_segment, payload_segment = signing_input.split('.', 1)

对第一部分 header_segment 进行 base64url 解码,得到 header。

对第二部分 payload_segment 进行 base64url 解码,得到 payload。

对第三部分 crypto_segment 进行 base64url 解码,得到 signature,针对 signature 部分数据进行合法性校验。

  • 拼接前两段解码前的密文,即:signing_input。
  • 从第一段明文中获取加密算法,默认值为:HS256。
  • 使用该算法加盐对 signing_input 进行加密,将得到的结果与 signature 密文进行比较,以验证签名一致性。

3. 代码实现

基于 Python 的 pyjwt 模块创建 JWT token。

安装依赖库。


pip3 install pyjwt

具体实现代码。


from datetime import datetime, timedelta

import jwt


class JwtToken(object):

    _salt = "@^4_00wedv**pi)+(!w1rwi=d3q4l=ie=g-u$s8jevmj*zgg2h" 

    _expire_message = dict(code=1200, msg="token 已经失效")

    _unknown_error_message = dict(code=4200, msg="token 解析失败")

    @classmethod
    def generate_token(cls, payload: dict) -> str:
        headers = dict(typ="jwt", alg="HS256")
        resut = jwt.encode(payload=payload, key=cls._salt, algorithm="HS256", headers=headers)
        return resut

    @classmethod
    def parse_token(cls, token: str) -> tuple:
        verify_status = False
        try:
            payload_data = jwt.decode(token, cls._salt, algorithms=['HS256'])
            verify_status = True
        except jwt.ExpiredSignatureError:
            payload_data = cls._expire_message
        except Exception as _err:
            payload_data = cls._unknown_error_message
        return verify_status, payload_data


if __name__ == '__main__':
    TEST_DATA = dict(name="mooor", exp=datetime.utcnow() - timedelta(seconds=1))
    token = JwtToken.generate_token(TEST_DATA)
    print(token)
    payload = JwtToken.parse_token(token)
    print(payload)

注意:exp(过期时间)务必选择 UTC 时间。

Expiration time will be compared to the current UTC time (as given by timegm(datetime.utcnow().utctimetuple())), so be sure to use a UTC timestamp or datetime in encoding

4. 参数介绍

4.1 示例:


import jwt
import datetime

dic = {
    'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1),  # 过期时间
    'iat': datetime.datetime.utcnow(),  #  开始时间
    'iss': 'ChaosMoor',                 #  签名
    'data': {                           #  内容,一般存放该用户id和开始时间
        'a': 1,
        'b': 2,
    },
}


token = jwt.encode(dic, 'secret', algorithm='HS256')                            # 加密生成字符串
print(token)

payload = jwt.decode(token, 'secret', issuer='lianzong', algorithms=['HS256'])  # 解密,校验签名
print(s)
print(type(s))

字典 dic 包含官方指定的 key,程序在解密时会根据 key 的值判断合法性。这些 key 包括:

"exp":在生成 token 时可设置该 token 的有效时间。若设置为 1 天过期,1 天后解析此 token 会抛出异常。

jwt.exceptions.ExpiredSignatureError: Signature has expired

"nbf":指该 token 的生效时间。若尝试使用但未到生效时间,则抛出异常。

jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)

"iss":token 的签发者(issuer)。可设置为字符串。接收时若不检验则无影响;若需检验但签名不一致,则抛出异常。

jwt.exceptions.InvalidIssuerError: Invalid issuer

"aud":指定了接收者(audience)。接收者在接收时必须提供与 token 要求一致的接收者(字符串)。若未写接收者或接收者不一致,则抛出异常。

jwt.exceptions.InvalidAudienceError: Invalid audience

"iat":token 的签发时间(issued at)。若当前时间在签发时间之前,则抛出异常。

jwt.exceptions.InvalidIssuedAtError: Issued At claim (iat) cannot be in the future.

4.2 PyJWT 官方文档

https://pyjwt.readthedocs.io/en/latest/usage.html

到此这篇关于Python JWT 介绍和使用详解的文章就介绍到这了,更多相关Python JWT使用内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表