You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask应用中从Flask-JWT迁移至PyJWT并替代@jwt_required()?

从Flask-JWT迁移到PyJWT:复刻@jwt_required()功能

我之前也踩过Flask-JWT停更的坑,迁移到PyJWT手动实现@jwt_required()其实比想象中简单,核心就是复刻Flask-JWT装饰器的几个关键动作——提取令牌、验证有效性、解析用户信息,咱们一步步来实现:

先明确@jwt_required()的核心作用

原来的@jwt_required()主要做了这几件事:

  • 检查请求中是否携带有效的JWT令牌
  • 验证令牌的签名、过期时间等合法性
  • 通过identify函数解析令牌payload,获取用户身份信息
  • 将用户信息挂载到请求上下文,方便后续视图函数使用

步骤1:准备依赖与配置

首先确保安装了PyJWT和加密依赖(处理签名算法):

pip install pyjwt cryptography

然后在Flask应用中配置密钥(和你原来Flask-JWT用的密钥保持一致):

from flask import Flask

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-strong-secret-key-here'  # 替换成你的实际密钥

步骤2:实现自定义的jwt_required装饰器

我们自己写一个装饰器,完全复刻原装饰器的逻辑:

import jwt
from flask import request, g, jsonify
from functools import wraps
from datetime import datetime, timedelta

def jwt_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        # 1. 从请求头提取令牌
        auth_header = request.headers.get('Authorization', None)
        if not auth_header:
            return jsonify({"error": "Authorization header missing"}), 401
        
        # 验证令牌格式是否为 Bearer <token>
        if not auth_header.startswith('Bearer '):
            return jsonify({"error": "Invalid Authorization format. Use 'Bearer <token>'"}), 401
        
        token = auth_header.split(' ')[1]
        
        try:
            # 2. 验证令牌合法性并解析payload
            payload = jwt.decode(
                token,
                app.config['SECRET_KEY'],
                algorithms=["HS256"],  # 和生成令牌时的算法保持一致
                options={"verify_exp": True}  # 自动验证过期时间
            )
        except jwt.ExpiredSignatureError:
            return jsonify({"error": "Token has expired"}), 401
        except jwt.InvalidTokenError:
            return jsonify({"error": "Invalid or tampered token"}), 401
        
        # 3. 执行原identify逻辑,将用户信息挂载到请求上下文
        g.user = identify(payload)
        
        # 4. 执行原视图函数
        return f(*args, **kwargs)
    return decorated_function

步骤3:复用你的identify函数

你原来的identify函数可以直接复用,甚至可以扩展(比如从数据库查询真实用户对象):

def identify(payload):
    user_id = payload['identity']
    # 如果需要从数据库获取完整用户信息,这里可以添加查询逻辑
    # 比如:return User.query.get(user_id)
    return {"user_id": user_id}

步骤4:在视图中使用自定义装饰器

用法和原来的@jwt_required()完全一致,还能通过Flask的g对象获取用户信息:

from flask_restful import Resource

class PrivateResource(Resource):
    @jwt_required
    def get(self):
        # 可以通过g.user访问解析后的用户信息
        return {
            "badge_number": 445566,
            "current_user_id": g.user['user_id']
        }

额外补充:生成JWT令牌的方法

如果需要生成新的令牌,用PyJWT的encode方法即可,和原来Flask-JWT的逻辑对齐:

def generate_access_token(user_id):
    payload = {
        "identity": user_id,
        "exp": datetime.utcnow() + timedelta(hours=24)  # 设置24小时过期
    }
    return jwt.encode(payload, app.config['SECRET_KEY'], algorithm="HS256")

注意事项

  • 确保生成令牌和验证令牌时使用相同的密钥和算法,否则会验证失败
  • 如果原来Flask-JWT有自定义的payload字段,迁移时要保持一致
  • g对象是Flask的请求上下文临时存储,仅在当前请求周期内有效,适合存放当前用户信息
  • 可以根据需求扩展装饰器,比如支持令牌放在查询参数中、允许可选令牌等

内容的提问来源于stack exchange,提问作者feners

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:52:31