API中JWT Token验证失败问题求助及代码排查
JWT验证失败排查(返回"Invalid token or expired token")
我正在构建API并实现JWT Token功能,目前能正常生成Token,但验证时总是返回detail="Invalid token or expired token."错误。移除验证逻辑的判断后,任意字符串都被视为有效,因此确定问题出在验证相关代码里。
原代码片段
第一段:JWT核心逻辑
# Responsible for signing, encoding, decoding and returning JWTs JWT_SECRET = config("secret") JWT_ALGORITHM = config("algorithm") # This returns the generated tokens def token_response(token: str): return { "access token": token } # This is used for signing the JWT string def signJWT(userID: str) -> Dict[str, str]: payload = { "userID": userID, "expiry": time.time() + 600 } token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) return token_response(token) def decodeJWT(token: str) -> dict: try: decode_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) return decode_token if decode_token['expires'] >= time.time() else None except: return {}
第二段:Bearer验证类
class JWTBearer(HTTPBearer): def __init__(self, auto_error: bool = True): super(JWTBearer, self).__init__(auto_error=auto_error) async def __call__(self, request: Request): credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request) if credentials: if not credentials.scheme == "Bearer": raise HTTPException(status_code=403, detail="Invalid authentication scheme.") if not self.verify_jwt(credentials.credentials): raise HTTPException(status_code=403, detail="Invalid token or expired token.") return credentials.credentials else: raise HTTPException(status_code=403, **detail="Invalid authorization code."**) def verify_jwt(self, jwtoken: str) -> bool: isTokenValid: bool = False try: payload = decodeJWT(jwtoken) except: payload = None if payload: isTokenValid = True return isTokenValid
问题分析与修复
核心问题点
- 键名不匹配:生成Token时payload用的是
expiry,但解码时错误访问decode_token['expires'],直接触发KeyError进入except分支,返回空字典,导致验证失败。 - 过期时间处理不规范:JWT标准使用
exp字段存储过期时间,且要求是整数时间戳;原代码自定义的expiry字段不符合规范,且jwt库本身会自动校验exp,无需手动判断。 - 语法错误:
__call__方法中抛出HTTPException时,错误使用**detail="...",应为detail="..."。 - 冗余异常捕获:
verify_jwt中的try块完全多余,decodeJWT已经处理了所有异常情况,反而会掩盖潜在问题。
修正后的代码
修正后的JWT核心逻辑
import time from typing import Dict import jwt # 替换为你的实际配置导入路径 from your_config_module import config JWT_SECRET = config("secret") JWT_ALGORITHM = config("algorithm") def token_response(token: str): return { "access token": token } def signJWT(userID: str) -> Dict[str, str]: # 使用JWT标准exp字段,存储整数时间戳 payload = { "userID": userID, "exp": int(time.time() + 600) } token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) return token_response(token) def decodeJWT(token: str) -> dict: try: # jwt.decode自动校验exp,无需手动判断 return jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) except jwt.ExpiredSignatureError: return None # 明确标记过期情况 except jwt.InvalidTokenError: return {} # 其他无效token情况
修正后的Bearer验证类
from fastapi import HTTPException, Request from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials class JWTBearer(HTTPBearer): def __init__(self, auto_error: bool = True): super(JWTBearer, self).__init__(auto_error=auto_error) async def __call__(self, request: Request): credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request) if credentials: if not credentials.scheme == "Bearer": raise HTTPException(status_code=403, detail="Invalid authentication scheme.") if not self.verify_jwt(credentials.credentials): raise HTTPException(status_code=403, detail="Invalid token or expired token.") return credentials.credentials else: # 修正语法错误 raise HTTPException(status_code=403, detail="Invalid authorization code.") def verify_jwt(self, jwtoken: str) -> bool: payload = decodeJWT(jwtoken) # 只要payload非空且非None,即为有效 return bool(payload)
内容的提问来源于stack exchange,提问作者Paulo Feresin
相关产品推荐
相关产品推荐

