【Fastapi】Token验证与Postman模拟测试
需求
好的,我们来润色一下这个需求,使其更清晰、更专业:
需求:实现 FastAPI 用户认证与授权系统
目标:
构建一个基于 FastAPI 的安全认证系统,实现用户登录、Token 生成与验证机制,并支持接口访问控制。
具体要求:
- 用户登录与 Token 生成:
- 提供
/login
(或类似路径) 接口,接收用户凭据(如用户名/密码)。 - 验证用户凭据的有效性。
- 如果验证成功,为该用户生成一个有效的访问 Token (例如使用 JWT)。
- 将生成的 Token 返回给客户端,客户端需在后续请求中携带此 Token。
- 提供
- Token 验证与受保护接口:
- 对于大多数 API 接口(称为“受保护接口”),在处理请求的业务逻辑之前,必须先验证客户端请求头中携带的 Token。
- 验证逻辑应检查 Token 是否存在、格式是否正确、是否有效(未过期、签名正确等)。
- 如果 Token 验证成功,则允许请求继续执行后续业务逻辑。
- 如果 Token 验证失败(无效、过期、缺失等),则应立即终止请求处理,并返回适当的错误响应(如 401 Unauthorized),引导客户端重新登录或获取有效 Token。
- 登录重定向/失败处理:
- 当 Token 验证失败时,应向客户端明确指示需要重新进行身份验证(登录)。
- 可以通过 HTTP 状态码(如 401)和响应体中的
WWW-Authenticate
头部或detail
字段来提示客户端。
- 接口白名单(公共接口):
- 定义一组特定的 API 接口路径(称为“白名单接口”或“公共接口”)。
- 对于这些白名单接口,访问时不需要验证 Token。
- 这使得某些基础服务或无需认证的操作(如注册、公开信息查询、登录接口本身等)可以被未认证用户访问。
- 实现方式建议:
- 使用 FastAPI 的
Depends
和OAuth2PasswordBearer
(配合Security
) 来实现认证流程和 Token 依赖。 - 可以使用中间件(Middleware)或依赖项(Dependency)来统一处理 Token 的验证逻辑。
- 使用 PyJWT 或类似库生成和验证 JWT Token。
- 使用
passlib
等库安全地处理密码哈希和验证。
总结:
该需求要求实现一个完整的、基于 Token 的 FastAPI 认证流程,包括登录、Token 生成、Token 验证以及针对不同接口的灵活访问控制(受保护接口需验证 Token,白名单接口无需验证)。同时,需要妥善处理认证失败的情况,引导用户重新登录。
- 使用 FastAPI 的
Code
以下是一个使用FastAPI实现用户登录、Token生成与验证的示例代码,包含白名单接口跳过Token验证的功能:
# -- coding:utf-8 --
from fastapi import FastAPI, Depends, HTTPException, status, Request
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.middleware.gzip import GZipMiddleware
from pydantic import BaseModel
from typing import Optional
import jwt
from datetime import datetime, timedelta
from passlib.context import CryptContext
from fastapi.encoders import jsonable_encoderapp = FastAPI()
app.add_middleware(GZipMiddleware)# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")# JWT配置
SECRET_KEY = "your-secret-key-here"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30# 模拟用户数据库
fake_users_db = {"mdwsw": {"username": "mdwsw","hashed_password": pwd_context.hash("mdwsw"),"disabled": False,}
}# 数据模型
class Token(BaseModel):access_token: strtoken_type: strclass TokenData(BaseModel):username: Optional[str] = Noneclass User(BaseModel):username: strdisabled: Optional[bool] = Noneclass UserInDB(User):hashed_password: str# OAuth2密码流
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login"