FastAPI 实现身份验证与授权

前言

在系统开发中,身份验证与授权是保障安全和隐私的关键。

  • 身份验证:确认用户身份,确保其合法性。常用技术包括 OAuth2.0JWT (JSON Web Token),可安全传递信息并降低服务器负载。
  • 授权:根据用户角色决定其访问权限。例如,管理员拥有完全控制权,普通用户仅能访问特定功能。

本次主要介绍 JWT 的鉴权和授权,JWT,全称为 JSON Web Token,是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象的形式安全地传输信息。JWT 通常被用作 Web 应用中的身份验证机制,也可以用于信息交换。它的结构由三部分组成:头部(Header)、载荷(Payload)和签名(Signature),各部分之间用点(.)分隔。

  • Header:包含令牌的元信息,例如签名算法(如 HMAC SHA256 或 RSA)。这部分会被 Base64 编码。
  • Payload:也称为声明(Claims),包含实际需要传输的数据,例如用户 ID、角色等。需要注意的是,虽然数据会编码,但并不加密,因此不应在 Payload 中防止敏感信息。
  • Signature:用于验证消息是否在传输过程中被篡改,同时也可以验证发送方的身份。签名是对 Header 和 Payload 进行 Base64 编码后,使用指定的算法和秘钥生成的。

JWT 的主要优点在于它的无状态性,这意味着服务器不需要存储令牌的相关信息,从而减少了服务器的负担。然而,这也带来了挑战,例如令牌的撤销较为困难。因此,在实际应用中,通常会结合短期有效时间和刷新机制来管理 JWT 的生命周期。

JWT 广泛应用于单点登录(SSO)、API 授权等场景,因其简洁、跨语言支持和易于实现的特点,称为现代 Web 开发中不可或缺的一部分。

第一步:了解 FastAPI 中的身份验证与授权

FastAPI 中,主要有两种方式来控制访问:

  1. 身份验证:验证用户的身份,通常通过令牌或凭据。
  2. 授权:根据用户的角色或权限,确定用户可以访问哪些资源。

我们将使用 JWT 令牌实现 安全的身份验证,并限制某些端点仅对已认证的用户开放。

为什么使用 JWT 进行身份验证?

  • 无状态:不需要服务器端会话。
  • 安全:令牌经过签名,防止篡改。
  • 广泛支持:JWT 与许多框架和库兼容。

第二部:设置 FastAPI JWT 身份验证

首先,我们需要一个用于创建和验证 JWT 令牌的包。我们安装 PyJWT 来处理 JWT。

pip install PyJWT

main.py 中,我们将定义一个基本设置,包含两个关键端点:

  • 一个 /login 端点,用于生成 JWT 令牌。
  • 一个 /protected 端点,仅允许经过身份验证的用户访问。

第三步:定义 JWT 身份验证工具

我们将创建用于生成和验证 JWT 的工具函数。SECRET_KEY 替换为生产环境中安全且唯一的密钥。

import uvicorn
import jwt
from datetime import datetime, timedelta
from fastapi import HTTPException, Security
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

SECRET_KEY = "asdffgadadaf"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


def create_jwt_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encode_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encode_jwt
  • create_jwt_token:接受数据并返回 JWT 令牌。
  • verify_jwt_token:解码并验证令牌,如果有效则返回有效载荷。

第四步:实现登录端点以生成 JWT 令牌

我们创建一个 /login 端点,用户可以通过提供凭据来获取 JWT。

from fastapi import HTTPException, Security, FastAPI, Depends, status
from pydantic import BaseModel

app = FastAPI()

fake_users_db = {
    "johndoe": {"username": "johndoe", "password": "secretpassword"}
}


class Login(BaseModel):
    username: str
    password: str


@app.post("/login")
async def login(user: Login):
    db_user = fake_users_db.get(user.username)
    if not db_user or db_user["password"] != user.password:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效的用户名或密码"
        )
    token_data = {"sub": user.username}
    token = create_jwt_token(token_data)
    return {"access_token": token, "token_type": "bearer"}
  • fake_users_db:一个虚拟用户数据库
  • /login 端点:验证用户,并在成功时返回访问令牌。

当用户使用有效凭据登录时,它们将收到一个 JWT 令牌,该令牌必须用于访问受保护的资源。

第五步:使用 JWT 身份验证保护端点

为了保护端点,我们将创建一个自定义依赖项,使用 HTTPBearer 类验证 JWT 令牌。

security = HTTPBearer()


async def get_current_user(credentials: HTTPAuthorizationCredentials = Security(security)):
    token = credentials.credentials
    payload = verify_jwt_token(token)
    if payload is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效或已过期的令牌"
        )
    return payload
  • get_current_user:从授权头中提取并验证 JWT。
  • HTTPBearer:提供 Bearer 令牌安全机制,通常用于 JWT 身份验证。

现在,我们将 get_current_user 作为依赖项应用于受保护的端点。

第六步:添加受保护的端点

我们添加一个 /protected 端点,仅允许经过身份验证的用户访问

@app.get("/protected")
async def protected_route(current_user: dict = Depends(get_current_user)):
    return {"message": f"你好,{current_user['sub']}! 你已通过身份验证。"}

通过 Depends(get_current_user),端点会检查用户是否经过身份验证并拥有有效令牌,然后才授予访问权限。这种设置限制了仅授权用户可以访问。

第七步:在 Swagger UI 中测试身份验证与授权

FastAPI 会自动更新 Swagger UI,以包含你的 JWT 身份验证端点:

  1. 访问 http://127.0.0.1:8000/docs
  2. 使用 /login 端点获取 JWT 令牌
  3. 授权:在 Swagger UI 中,使用 “授权” 按钮输入 JWT 令牌。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值