ai
  • index
  • 1.首页
  • 2.介绍
  • 3.架构概览
  • 4.服务器概念
  • 5.客户端概念
  • 6.版本控制
  • 7.连接到远程MCP服务器
  • 8.连接到本地MCP服务器
  • json_rpc
  • 9.构建一个MCP服务器
  • 10.检查员
  • 11.构建一个MCP客户端
  • 14.架构
  • 15.基础协议概述
  • 16.生命周期
  • 17.传输
  • 18.授权
  • 19.安全最佳实践
  • 20.取消
  • 21.Ping
  • 22.进展
  • 23.Roots
  • 24.采样
  • 25.启发
  • 26.服务器特性
  • 27.提示词
  • 28.资源
  • 29.工具
  • 30.完成
  • 31.日志记录
  • 32.分页
  • 33.架构参考
  • URI模板
  • 12.实现
  • http.server
  • 动态客户端注册协议
  • 受保护资源元数据
  • 授权服务器元数据
  • JWKS
  • PKCE
  • PyJWT
  • secrets
  • watchfiles
  • 实现authorization
  • 实现cancel
  • 实现completion
  • 实现logging
  • 实现pagination
  • 实现process
  • 实现transport
  • psutil
  • pytz
  • zoneinfo
  • contextlib
  • Starlette
  • mcp.1.starter
  • mcp.2.Resource
  • mcp.3.structured_output
  • mcp.4.prompts
  • mcp.5.context
  • mcp.6.streamable
  • mcp.7.lowlevel
  • mcp.8.Completion
  • mcp.9.Elicitation
  • mcp.10.oauth
  • mcp.11.integration
  • mcp.12.best
  • mysql-mcp
  • databases
  • uvicorn
  • asynccontextmanager
  • AsyncExitStack
  • streamable
  • aiohttp
  • publish
  • email
  • schedule
  • twine
  • 1.教学文档总览
  • 2.教师使用指南
  • 3.教学系统快速参考
  • 4.新生入门指南
  • 5.学生使用指南
  • 1. PyJWT
    • 1.1. 安装 PyJWT
  • 2. 核心功能
    • 2.1. 编码(生成) JWT
    • 2.2. 解码(验证) JWT
  • 3. 支持的算法
  • 4. 高级用法
    • 4.1. 使用 RSA 非对称加密
    • 4.2. 自定义 Claims (声明)
    • 4.3. 验证选项
  • 5. 实际应用示例
    • 5.1. Flask JWT 认证
    • 5.2. Django REST Framework JWT(最小可运行示例,单文件)
  • 6. 安全最佳实践
  • 7. 性能考虑

1. PyJWT #

这一部分介绍 PyJWT 的定位与用途。PyJWT 是用于在 Python 中生成与验证 JSON Web Token 的库。JWT 遵循 RFC 7519 标准,可在不同服务之间安全、紧凑地传递声明信息,常用于认证与授权、分布式服务间信任传递等场景。

1.1. 安装 PyJWT #

下面演示在 Windows 环境中使用 py -m pip 安装 PyJWT 以及可选的加密支持。若需要 RSA/EC 等非对称算法,请一并安装带加密依赖的可选组件。

REM 升级 pip,避免旧版本导致安装报错
py -m pip install --upgrade pip

REM 安装 PyJWT(基础版本,包含 HS256 等对称算法)
py -m pip install pyjwt

REM 安装带加密依赖的 PyJWT(支持 RSA/EC 等非对称算法)
py -m pip install "pyjwt[crypto]"

2. 核心功能 #

本节演示最常用的编码(生成 Token)与解码(验证 Token)能力。示例均为可独立运行的完整脚本形式,并提供逐行中文注释以便理解。

2.1. 编码(生成) JWT #

本示例演示使用 HS256(对称加密)生成一个带有过期时间的 Token。

# 导入 PyJWT 库
import jwt
# 从 datetime 导入时间工具以便设置过期时间
from datetime import datetime, timedelta

# 定义主函数,便于脚本独立运行
def main():
    # 定义载荷字典开始
    payload = {
        # 用户唯一标识
        'user_id': 123,
        # 用户名
        'username': 'john_doe',
        # 过期时间(当前 UTC 时间 + 1 小时)
        'exp': datetime.utcnow() + timedelta(hours=1)
    }
    # 定义对称密钥,仅服务端保存
    secret_key = 'your-secret-key'
    # 使用 HS256 算法对载荷进行签名,生成 JWT 字符串(PyJWT>=2 返回 str)
    token = jwt.encode(payload, secret_key, algorithm='HS256')
    # 打印生成的 Token,供后续验证或传输
    print(token)

# 作为脚本入口执行主函数
if __name__ == '__main__':
    main()

2.2. 解码(验证) JWT #

本示例先生成一个 Token,然后演示如何在验证签名、校验过期时间的前提下进行解码,并完整处理常见异常。

# 导入 PyJWT 库
import jwt
# 导入时间工具以生成带过期时间的 Token
from datetime import datetime, timedelta

# 定义主函数,演示生成与解码流程
def main():
    # 构造载荷并设置 1 小时后过期
    payload = {
        # 用户唯一标识
        'user_id': 123,
        # 用户名
        'username': 'john_doe',
        # 过期时间(当前 UTC 时间 + 1 小时)
        'exp': datetime.utcnow() + timedelta(hours=1)
    }
    # 对称密钥,与生成时保持一致
    secret_key = 'your-secret-key'
    # 先生成一个 HS256 Token 以供演示
    token = jwt.encode(payload, secret_key, algorithm='HS256')
    # 尝试解码 Token,验证签名与过期时间(需显式提供 algorithms)
    try:
        # 解码并返回载荷(若已过期或签名不匹配会抛异常)
        decoded_payload = jwt.decode(token, secret_key, algorithms=['HS256'])
        # 打印解码结果
        print(decoded_payload)
    # 捕获过期错误
    except jwt.ExpiredSignatureError:
        # 说明 Token 已超过 exp 设置的时间
        print('Token已过期')
    # 捕获通用无效 Token 错误
    except jwt.InvalidTokenError:
        # 说明签名不合法或结构错误等
        print('无效Token')

# 脚本入口
if __name__ == '__main__':
    main()

3. 支持的算法 #

PyJWT 同时支持对称加密(如 HS256)与非对称加密(如 RS256、ES256)等多种算法。对称加密仅需共享密钥;非对称加密使用公私钥对,更适合多服务间的安全验证与密钥分离。生产环境通常优先考虑非对称以降低密钥泄露影响面。

算法类型 算法名称 说明
对称加密 HS256, HS384, HS512 使用共享密钥
非对称加密 RS256, RS384, RS512 RSA 签名
非对称加密 ES256, ES384, ES512 ECDSA 签名
无加密 none 不推荐生产环境使用

4. 高级用法 #

本节展示 RSA 非对称签名、带标准与自定义声明的载荷、以及解码时的高级校验选项,便于满足更严格的安全与合规需求。

4.1. 使用 RSA 非对称加密 #

此示例动态生成 RSA 公私钥对,用私钥签名、用公钥验证,适合服务端签发、客户端或其他服务端验证的场景。

# 导入 PyJWT 库
import jwt
# 导入生成与管理密钥所需的组件(本示例不直接序列化密钥,保留以示范)
from cryptography.hazmat.primitives import serialization
# 导入 RSA 算法支持
from cryptography.hazmat.primitives.asymmetric import rsa
# 导入默认后端
from cryptography.hazmat.backends import default_backend

# 定义主函数
def main():
    # 生成 RSA 私钥(实际生产中请妥善保存,不要硬编码或外泄)
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    # 从私钥导出公钥,用于验证签名
    public_key = private_key.public_key()
    # 定义待签名的载荷(可根据业务扩展)
    payload = {'user': 'admin'}
    # 使用 RS256 算法与私钥签名,得到 Token
    token = jwt.encode(payload, private_key, algorithm='RS256')
    # 使用公钥验证签名并解码 Token
    decoded = jwt.decode(token, public_key, algorithms=['RS256'])
    # 打印解码结果
    print(decoded)

# 脚本入口
if __name__ == '__main__':
    main()

4.2. 自定义 Claims (声明) #

示例演示如何在载荷中包含标准声明(iss、sub、aud、iat、exp、nbf、jti)与自定义数据,并在解码时对签发者与接收方进行严格校验,有助于提升安全性与契约清晰度。

# 导入 PyJWT 及时间工具
import jwt
# 导入 datetime 以便构造时间相关声明
from datetime import datetime, timedelta

# 定义主函数
def main():
    # 开始定义载荷字典
    payload = {
        # 签发者(Issuer)
        'iss': 'my-app',
        # 主题(Subject)
        'sub': 'user-auth',
        # 接收方(Audience)
        'aud': 'client-app',
        # 签发时间(Issued At)
        'iat': datetime.utcnow(),
        # 过期时间(Expiration Time)
        'exp': datetime.utcnow() + timedelta(days=1),
        # 生效时间(Not Before)
        'nbf': datetime.utcnow(),
        # Token 唯一标识(JWT ID)
        'jti': 'unique-token-id',
        # 自定义数据(业务相关)
        'custom_data': {
            # 用户角色
            'user_role': 'admin',
            # 偏好设置
            'preferences': {'theme': 'dark'}
        }
    }
    # 对称密钥
    secret_key = 'your-secret-key'
    # 编码生成 Token
    token = jwt.encode(payload, secret_key, algorithm='HS256')
    # 解码并验证签发者与接收方
    decoded = jwt.decode(
        # 待解码的 Token
        token,
        # 解码所需密钥
        secret_key,
        # 指定可接受的算法列表
        algorithms=['HS256'],
        # 期望的接收方
        audience='client-app',
        # 期望的签发者
        issuer='my-app'
    )
    # 打印解码结果
    print(decoded)

# 脚本入口
if __name__ == '__main__':
    main()

4.3. 验证选项 #

通过 options 可以细化解码时的校验行为,例如是否校验签名、是否要求存在某些标准字段等。示例中我们开启常用校验并提供 aud 与 iss 以通过验证。

# 导入 PyJWT 与时间工具
import jwt
# 导入 datetime 用于构造时间声明
from datetime import datetime, timedelta

# 定义主函数
def main():
    # 准备载荷,包含必要字段以通过各项校验
    payload = {
        # 签发者(Issuer)
        'iss': 'my-app',
        # 接收方(Audience)
        'aud': 'client-app',
        # 签发时间(Issued At)
        'iat': datetime.utcnow(),
        # 过期时间(Expiration Time),设置为 5 分钟
        'exp': datetime.utcnow() + timedelta(minutes=5)
    }
    # 对称密钥
    secret_key = 'your-secret-key'
    # 生成 Token
    token = jwt.encode(payload, secret_key, algorithm='HS256')
    # 使用严格的解码与校验选项
    decoded = jwt.decode(
        # 待解码的 Token
        token,
        # 用于验证签名的密钥
        secret_key,
        # 指定允许的算法
        algorithms=['HS256'],
        # 细化验证行为的选项
        options={
            # 验证签名
            'verify_signature': True,
            # 验证过期时间
            'verify_exp': True,
            # 验证签发时间
            'verify_iat': True,
            # 验证接收方
            'verify_aud': True,
            # 要求必须包含 exp
            'require_exp': True,
            # 可选是否要求包含 iat(此处不强制)
            'require_iat': False
        },
        # 期望的接收方
        audience='client-app',
        # 期望的签发者
        issuer='my-app'
    )
    # 打印结果
    print(decoded)

# 脚本入口
if __name__ == '__main__':
    main()

5. 实际应用示例 #

这里给出两个最常见的 Web 场景:Flask 与 Django REST Framework(DRF)。两个示例都是可独立运行的最小化应用,便于本地快速体验;生产环境请补充完整的认证流程与错误处理。

5.1. Flask JWT 认证 #

示例提供一个 /login 接口用于签发 Token,以及一个受保护的 /protected 接口用于验证 Token。

# 导入 Flask Web 框架中需要的对象
from flask import Flask, request, jsonify
# 导入 PyJWT 库
import jwt
# 导入 datetime 以便设置过期时间
import datetime

# 创建 Flask 应用实例
app = Flask(__name__)
# 设置应用级密钥(演示用)
app.config['SECRET_KEY'] = 'your-secret-key'

# 定义登录接口,使用 Basic Auth 进行最简演示
@app.route('/login', methods=['POST'])
# 登录视图函数
def login():
    # 从请求头解析基础认证信息
    auth = request.authorization
    # 极简校验:密码为 'password' 则签发 Token(实际请使用数据库与加密校验)
    if auth and auth.password == 'password':
        # 生成 30 分钟有效期的 Token:开始构造载荷字典
        payload = {
            # 用户名来源于认证信息
            'user': auth.username,
            # 过期时间设置为 30 分钟
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
        }
        # 使用应用密钥进行编码
        token = jwt.encode(payload, app.config['SECRET_KEY'])
        # 返回 JSON,其中包含签发的 Token
        return jsonify({'token': token})
    # 认证失败时返回 401
    return jsonify({'message': 'Invalid credentials'}), 401

# 定义受保护接口,需要提供 token 参数
@app.route('/protected')
# 受保护视图函数
def protected():
    # 从查询字符串中获取 token(生产环境推荐使用 Authorization 头)
    token = request.args.get('token')
    # 尝试解码并返回载荷
    try:
        # 解码并验证签名
        data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        # 返回业务数据
        return jsonify({'data': data})
    # 捕获异常并返回 403
    except Exception:
        # Token 缺失、格式错误或签名/过期校验失败
        return jsonify({'message': 'Invalid token'}), 403

# 以调试模式启动应用
if __name__ == '__main__':
    # 指定端口为 8000,便于与后续示例区分
    app.run(debug=True, port=8000)

5.2. Django REST Framework JWT(最小可运行示例,单文件) #

此示例以单文件方式动态配置 Django 与 DRF,提供 /token(签发 Token)与 /secure(验证 Token)两个接口,便于无需完整项目结构即可快速运行与测试。

# 导入标准库 os(此处未直接使用,保留结构完整性)
import os
# 导入 sys 以便复用命令行入口
import sys
# 导入 PyJWT
import jwt
# 导入时间工具
from datetime import datetime, timedelta
# 导入 Django 设置与 URL 构造工具
from django.conf import settings
from django.urls import path
# 导入 Django 响应对象(示例未直接使用)
from django.http import JsonResponse
# 导入运行开发服务器所需函数
from django.core.management import execute_from_command_line
# 导入 WSGI 应用构造(示例未直接使用)
from django.core.wsgi import get_wsgi_application
# 导入 DRF 视图与响应
from rest_framework.views import APIView
from rest_framework.response import Response

# 若未配置 Django 设置,则进行最小化配置
if not settings.configured:
    # 调用 settings.configure 进行基本配置
    settings.configure(
        # 打开调试模式
        DEBUG=True,
        # 设置开发密钥(示例用)
        SECRET_KEY='dev-secret',
        # 将当前模块作为 URL 路由入口
        ROOT_URLCONF=__name__,
        # 允许所有主机访问(开发环境)
        ALLOWED_HOSTS=['*'],
        # 关闭中间件以简化示例
        MIDDLEWARE=[],
        # 注册必要的应用(contenttypes/auth 为 DRF 依赖)
        INSTALLED_APPS=[
            'django.contrib.contenttypes',
            'django.contrib.auth',
            'rest_framework',
        ],
    )

# 初始化 Django(必须在定义视图前调用)
import django
# 调用 setup 完成应用注册与配置加载
django.setup()

# 定义一个视图用于签发 Token
class TokenView(APIView):
    # 提供 GET 接口以简化测试(实际可用 POST 并验证用户)
    def get(self, request):
        # 读取查询参数中的用户名(默认 guest)
        username = request.GET.get('user', 'guest')
        # 构造载荷字典,设置 10 分钟过期
        payload = {
            # 将用户名放入载荷,便于下游识别
            'user': username,
            # 设置过期时间为 10 分钟
            'exp': datetime.utcnow() + timedelta(minutes=10)
        }
        # 使用与验证一致的对称密钥
        secret = 'your-secret-key'
        # 生成 Token
        token = jwt.encode(payload, secret, algorithm='HS256')
        # 返回 JSON
        return Response({'token': token})

# 定义受保护视图,验证 Authorization 头中的 Bearer Token
class SecureDataView(APIView):
    # 简单示例不强制身份认证类,直接验证 Token
    def get(self, request):
        # 从 Authorization 头获取内容
        auth = request.headers.get('Authorization', '')
        # 按空格拆分,期待格式为 Bearer <token>
        parts = auth.split()
        # 判断是否满足 Bearer 格式
        if len(parts) == 2 and parts[0].lower() == 'bearer':
            # 取出 token 部分
            token = parts[1]
            # 尝试解码并验证签名
            try:
                # 解码 Token,校验签名
                payload = jwt.decode(token, 'your-secret-key', algorithms=['HS256'])
                # 成功则返回用户信息
                return Response({'ok': True, 'user': payload.get('user')})
            # 捕获过期错误
            except jwt.ExpiredSignatureError:
                # 返回 401 未授权,提示过期
                return Response({'ok': False, 'error': 'expired'}, status=401)
            # 捕获通用无效 Token 错误
            except jwt.InvalidTokenError:
                # 返回 401 未授权,提示无效
                return Response({'ok': False, 'error': 'invalid'}, status=401)
        # 若未提供或格式不正确
        return Response({'ok': False, 'error': 'missing bearer token'}, status=400)

# 绑定 URL 到视图
urlpatterns = [
    # 获取 Token 的接口
    path('token', TokenView.as_view()),
    # 需要携带 Bearer Token 才能访问的接口
    path('secure', SecureDataView.as_view()),
]

# 运行开发服务器(默认端口 8001,避免与 Flask 冲突)
if __name__ == '__main__':
    # 启动 Django 开发服务器
    execute_from_command_line([sys.argv[0], 'runserver', '8001'])

6. 安全最佳实践 #

以下建议有助于更安全地使用 JWT:

  • 永远不要在 JWT 载荷中放置明文敏感信息(如密码、密钥、私密个人信息)。
  • 使用强随机密钥,并定期轮换;生产环境建议使用 KMS/密钥管理服务。
  • 合理设置过期时间(短生命周期),并结合刷新令牌机制。
  • 解码时严格验证必要声明(iss、aud、exp 等),并处理所有异常分支。
  • 全链路使用 HTTPS 传输,避免 Token 被窃听。
  • 服务端应具备 Token 吊销策略(黑名单/版本号/会话表)。

7. 性能考虑 #

对称算法(HS)通常更快;非对称算法(RS/ES*)安全边界更清晰但计算更重。对解码路径进行缓存或集中验证可降低系统开销。

  • HS256 相比 HS512 有更好的性能,但安全性略低;结合威胁模型选择合适算法。
  • 解码操作通常比编码更耗时,热点路径需关注。
  • 在多实例/多服务场景中,可集中化验证或引入网关以复用验证结果。

PyJWT 是 Python 生态中成熟可靠的 JWT 实现。配合正确的密钥管理、声明校验与异常处理策略,可构建健壮的认证与授权体系。

访问验证

请输入访问令牌

Token不正确,请重新输入