FastAPI使用python-jose遇JWTError: Not enough segments错误求助
解决python-jose的JWTError: Not enough segments错误
这个错误的核心原因是JWT格式无效,结合你的代码来看,主要有以下几个问题需要修复:
1. 生成Token接口的返回字段错误
你的/token接口返回的是"access_type"字段,但FastAPI的OAuth2PasswordBearer(也就是你用的oauth2_scheme)遵循OAuth2标准,期望的token字段名是access_token。字段名不匹配会导致前端无法正确获取并传递token,最终传递给jwt.decode的是无效值(甚至是空字符串),触发Not enough segments错误。
修复后的login_access_token接口:
@router.post("/token", response_model=Token, tags=['login']) async def login_access_token( db_session: AsyncSession = Depends(get_async_session), form_data: OAuth2PasswordRequestForm = Depends() ): user = await crud_user.authenticate(db_session=db_session, email=form_data.username, password=form_data.password) if not user: raise HTTPException( status_code=404, detail="Incorrect password or username" ) elif not await crud_user.is_active(user): raise HTTPException( status_code=400, detail="Inactive user" ) access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": await create_access_token( # 修改字段名为access_token data={"user_id": user.id}, expires_delta=access_token_expires ), "token_type": "bearer" }
2. get_current_user函数的两处问题
- 重复调用
jwt.decode,属于冗余代码,直接删除重复行 - 异常捕获类型错误:当前使用的是
python-jose库,应捕获jose.exceptions.JWTError而非PyJWTError(后者是PyJWT库的异常类)
修复后的get_current_user函数:
from jose.exceptions import JWTError # 确保导入正确的异常类 async def get_current_user( db: AsyncSession = Depends(get_async_session), token: str = Security(oauth2_scheme) ): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) token_data = Token(**payload) except JWTError: raise HTTPException( status_code=HTTP_403_FORBIDDEN, detail="Could not validate credentials" ) user = await crud_user.get(db, id=token_data.id) if not user: raise HTTPException(status_code=404, detail="User not found") return user
3. 额外验证:Payload字段匹配问题
你的create_access_token中传入的是{"user_id": user.id},但Token模型解析的是payload里的id字段,这会导致Token(**payload)初始化失败。需要二选一修改:
- 修改
create_access_token的传入数据:# 调用时修改data的key为id create_access_token(data={"id": user.id}, expires_delta=access_token_expires) - 或者修改
Token模型的字段:class Token(BaseModel): user_id: int # 保留其他必要字段...
总结
优先修复返回字段名的问题(这是触发Not enough segments的直接原因),再处理异常捕获和payload字段匹配问题,即可解决当前错误。
内容的提问来源于stack exchange,提问作者Слава Заблоцкий
相关产品推荐
相关产品推荐

