【FastAPI】在FastAPI中实现用户登录和Token认证(JWT)并展示到Swagger UI

在FastAPI中实现用户登录和Token认证(JWT)并展示到Swagger UI

在现代的Web应用中,用户认证是非常关键的部分。无论是构建一个简单的API还是复杂的Web应用,保护用户数据和验证用户身份都是必不可少的。JWT(JSON Web Token)是一种非常流行的认证机制,结合FastAPI的强大功能,可以轻松实现基于Token的用户认证。

在本文中,我们将介绍如何在FastAPI中实现用户登录,生成JWT Token,并通过该Token保护API路由。同时,我们还会展示如何在Swagger UI中使用这些接口进行测试和演示。


为什么选择JWT进行认证?

JWT(JSON Web Token)是一种紧凑的、URL安全的令牌格式,广泛应用于身份验证和信息交换。它有以下几个优势:

  • 轻量化:JWT是基于JSON格式的,传输数据量小,适合用于Web环境。
  • 自包含:JWT包含了所需的所有信息,如用户的身份信息、签发时间、过期时间等,避免了每次请求都需要查询数据库。
  • 易于验证:服务器只需要对JWT进行签名验证即可判断其合法性。

使用JWT的典型流程如下:

  1. 用户通过用户名和密码进行登录。
  2. 服务器验证用户名和密码,并生成JWT令牌。
  3. 用户在之后的请求中附带该JWT进行认证,服务器验证该JWT的合法性和有效性。

创建FastAPI应用并实现JWT认证

我们将分步骤展示如何使用FastAPI实现用户登录和JWT认证。

1. 安装依赖

在开始之前,我们需要安装fastapipyjwtfastapi用于构建API,pyjwt用于生成和验证JWT。

bash 复制代码
pip install fastapi[all] pyjwt
2. 定义FastAPI应用

我们将创建一个FastAPI应用,并实现以下功能:

  • 用户登录并获取JWT Token
  • 使用JWT保护API路由
  • 在Swagger UI中展示这些API
python 复制代码
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from datetime import datetime, timedelta
from typing import Optional
import jwt

# 创建FastAPI应用
app = FastAPI()

# 定义密钥和算法
SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

# 模拟用户数据库
fake_users_db = {
    "user1": {
        "username": "user1",
        "full_name": "User One",
        "email": "user1@example.com",
        "hashed_password": "fakehashedpassword",
        "disabled": False,
    }
}

# 用于验证用户名和密码
def fake_hash_password(password: str):
    return "fakehashed" + password

# 定义用户模型
class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None

class UserInDB(User):
    hashed_password: str

# OAuth2PasswordBearer会创建一个依赖项来验证令牌
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# 获取用户信息
def get_user(db, username: str):
    if username in db:
        user_dict = db[username]
        return UserInDB(**user_dict)

# 验证用户是否有效
def authenticate_user(db, username: str, password: str):
    user = get_user(db, username)
    if not user:
        return False
    if not user.hashed_password == fake_hash_password(password):
        return False
    return user

# 生成访问令牌
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# 登录并获取Token的路由
@app.post("/token", response_model=dict)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

# 依赖项,通过Token获取当前用户
async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except jwt.PyJWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username)
    if user is None:
        raise credentials_exception
    return user

# 依赖项,获取当前激活的用户
async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user

# 受保护的路由
@app.get("/users/me", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user
3. 代码说明
  • 用户登录和Token生成

    用户通过/token接口提交用户名和密码。我们在数据库(假设为fake_users_db)中验证用户的凭据。验证通过后,生成JWT Token并返回给用户。

  • JWT验证

    使用jwt.encode生成Token,jwt.decode解析Token。Token中存储了用户的身份信息(sub字段),并且有过期时间。

  • 保护路由

    使用依赖项Depends(oauth2_scheme)来获取请求头中的Token,然后使用get_current_active_user函数对Token进行验证。只有通过验证的用户才能访问受保护的路由。

  • Swagger UI

    FastAPI自带的Swagger文档支持会自动生成所有API接口的文档,并且在/docs页面展示。我们可以通过该页面直接测试用户登录、Token生成、以及受保护的路由。

4. 在Swagger UI中测试

FastAPI自动生成的Swagger文档页面可以极大地方便我们测试API。

  • 打开浏览器,访问http://localhost:8000/docs
  • 在Swagger页面上,你会看到所有定义的API接口,包括/token/users/me
1. 获取Token
  • 点击/token接口,点击Try it out
  • 输入用户名user1和密码password
  • 点击Execute,你将看到返回的JWT Token。
2. 使用Token访问受保护的接口
  • 在Swagger页面的右上角,点击Authorize按钮。
  • 在弹出的窗口中,输入获取到的Token(以Bearer开头)。
  • 点击/users/me接口,点击Try it out,你将看到当前登录用户的信息。

总结

通过本文的示例,你学到了如何使用FastAPI实现用户登录、JWT Token认证,并在Swagger UI中展示这些API接口。JWT是一种轻量化、安全的用户认证方式,结合FastAPI的高性能和易用性,可以帮助你快速构建出具备用户认证功能的API。

你可以根据需求进一步扩展这个示例,如集成数据库、实现更复杂的用户权限管理等等。使用FastAPI,处理这些功能会变得非常简单而高效。希望这个示例对你有所帮助!

相关推荐
一个王同学19 分钟前
从零到一 | CV转多模态大模型 | week19 | 基于 FastAPI 和 vLLM 的多模态大模型部署
人工智能·深度学习·计算机视觉·fastapi·改行学it·vllm
像风一样自由20202 小时前
从本地到公网:Windows 下使用 Cloudflare Quick Tunnel 与 Natapp 联调 FastAPI
windows·fastapi
心如鉄补4 小时前
FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“
人工智能·fastapi
Kim.Li10 小时前
格式塔设计原则全解析:12项核心原则在 UI/UX 中的实战应用指南
ui·产品经理·ux·视觉设计·交互设计
ye小杰榨 问鼎中原ZP13 小时前
初探:用 FastAPI 搭建你的第一个 AI Agent 接口
人工智能·fastapi
jin12332214 小时前
HarmonyOS ArkTS API 24实现声明式 UI 框架与 @Builder 组件复用模式构建三标签页智能账单应用
ui·华为·harmonyos
雨辰AI1 天前
全集实战:企业级大模型服务化部署全栈指南|FastAPI 封装 + Nginx 负载均衡 + 高可用架构 从单机到生产一步到位
人工智能·ai·负载均衡·fastapi·ai编程
Getflare1 天前
前端 + UI 设计 + AI:这不是三个工种,是一个新三角能力模型(附自检清单)
前端·人工智能·ui
达子6661 天前
第9章_HarmonyOs图解 用Java开发UI
java·ui·harmonyos
李昊哲小课2 天前
FastAPI 猫咖预约系统 API
人工智能·python·fastapi