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

Python使用JWT库时如何提取已过期JWT令牌的payload内容

问题根因

PyJWT的jwt.decode()方法默认开启全量校验(包含签名合法性、令牌过期时间校验等),你当前代码中令牌一旦过期,jwt.decode()会直接抛出jwt.ExpiredSignatureError异常,此时存储payload的data变量尚未完成赋值,异常捕获分支调用data["sub"]["username"]自然会触发报错。
另外你现有代码还存在逻辑漏洞:空token判断分支中仍然调用了jwt.decode(token, secretKey, algorithms=algorithm),token为空时该行会直接抛出异常,和你预期抛出"Token is missing"的逻辑不符。

修复方案

你可以通过jwt.decode()的options参数跳过指定校验项,先拿到payload再做后续校验逻辑,修改后的代码如下:

import jwt
from flask import request
from functools import wraps
from werkzeug.exceptions import Forbidden, Unauthorized

def admin_rights_required(f):
    @wraps(f)
    def _decorated(*args, **kwargs):
        config = readConfig()
        secretKey = config["JWT_SECRET_KEY"]
        algorithm = config["JWT_ENCODING_ALGORITHM"]
        token = None
        payload = None
        if "Authorization" in request.headers:
            auth_header = request.headers["Authorization"]
            token = auth_header.replace("Bearer ", "")
        
        # 先处理空token场景
        if not token:
            raise Unauthorized("Token is missing")
        
        try:
            # 先跳过过期校验拿到payload,确保后续异常分支可访问用户信息
            payload = jwt.decode(token, secretKey, algorithms=algorithm, options={"verify_exp": False})
            
            # 再做正常全量校验(包含过期校验)
            jwt.decode(token, secretKey, algorithms=algorithm)
            
            if not _ruleUserObj.getRuleUserFromToken(token):
                raise jwt.InvalidTokenError
            if getTokenDurationDifference(token) == -1:
                raise jwt.InvalidTokenError
            currentUser = _ruleUserObj.getRuleUser(payload["sub"]["username"])
            if not len(currentUser) > 0:
                raise jwt.InvalidTokenError
            if currentUser["isAdmin"] == False:
                raise Forbidden()
        except jwt.ExpiredSignatureError:
            # 此时payload已经提前赋值,可以正常访问
            _ruleUserObj.updatedRuleUserSessionRemToken(payload["sub"]["username"])
            raise Unauthorized("Signature expired. Please log in again.")
        except jwt.InvalidTokenError:
            # 合法签名的无效token才需要清理会话,非法签名的token payload不可信可以跳过
            if payload and "sub" in payload and "username" in payload["sub"]:
                _ruleUserObj.updatedRuleUserSessionRemToken(payload["sub"]["username"])
            raise Unauthorized("Invalid token. Please log in again.")

        return f(*args, **kwargs)

    return _decorated
核心修改点说明
  • 提前通过options={"verify_exp": False}跳过过期校验拿到payload,确保所有异常分支都能访问到有效签名令牌的用户信息
  • 修复了空token场景下的逻辑错误,空token直接返回对应提示,不会触发无效解码
  • 对InvalidTokenError分支增加了payload合法性判断,避免被伪造的无效令牌触发代码报错

内容的提问来源于stack exchange,提问作者SUNEEL KAUSHIK S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:15:00