如何在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
相关产品推荐
相关产品推荐

