【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,处理这些功能会变得非常简单而高效。希望这个示例对你有所帮助!

相关推荐
五羟基己醛2 小时前
【学习笔记】SquareLine Studio安装教程(LVGL官方工具)
笔记·学习·ui
Logrus IT2 小时前
跨平台应用程序本地化过程的特点
ui·软件工程·ux
向宇it1 天前
【unity进阶知识10】从零手搓一个UI管理器/UI框架,自带一个提示界面,还有自带DOTween动画效果
ui·unity·游戏引擎
red_redemption1 天前
UGUI(三大现成UI控件)
ui
科雷软件测试2 天前
selenium的webdriver常用方法和属性介绍(2)
python·selenium·ui·自动化
无敌开心2 天前
fastAPI教程:路由操作及HTTP请求响应
网络协议·http·fastapi
theoxiong2 天前
深度解析:Tkinter 界面布局与优化技巧
python·ui·pyqt·tkinter
RangoLei_Lzs2 天前
C++模版SFIANE应用踩的一个小坑
java·开发语言·ui