13 FastAPI集成OAuth 2.0 认证

在构建现代 Web 应用时,API 安全性和认证机制至关重要。OAuth 2.0 是一种流行的开放标准,它允许第三方应用授权用户的资源而不暴露用户的凭证(如密码)。在本文中,我们将介绍 OAuth 2.0 认证机制,并结合 FastAPI 实现 OAuth 2.0 授权流程,展示如何集成 JWT(JSON Web Token) 进行用户认证和授权。

1. 认证机制简介:API 安全和认证

在 Web 应用中,认证(Authentication)是确认用户身份的过程,而授权(Authorization)是验证用户是否有权限访问某些资源的过程。安全的 API 需要确保:

  1. 身份验证:确认请求是由合法用户发起的。
  2. 权限控制:确保用户只访问自己有权限的资源。

OAuth 2.0 是一种常用的授权框架,它使用户能够授权第三方应用访问其受保护的资源,而无需暴露自己的凭证。通过 OAuth 2.0,用户可以授权某个应用访问其数据(如 Google、GitHub 等服务),而不需要直接与该应用共享密码。

1.1 OAuth 2.0 授权流程

OAuth 2.0 授权流程分为几个关键步骤:

  1. 客户端请求授权:客户端(应用)请求用户授权,通常是通过一个授权码流程。
  2. 用户授权:用户同意授权,授权服务器向客户端返回一个授权码。
  3. 客户端交换授权码:客户端使用授权码向授权服务器请求访问令牌(Access Token)。
  4. 访问资源:客户端使用访问令牌访问受保护的资源。

1.2 JWT(JSON Web Token)

JWT 是一种常用于认证和信息交换的开放标准。它包含了三个部分:

  1. Header:定义签名的类型和加密算法。
  2. Payload:包含声明(Claims),如用户身份、权限等信息。
  3. Signature:使用加密算法对 Header 和 Payload 进行签名,用于验证数据的完整性。

JWT 广泛应用于 OAuth 2.0 授权流程中作为访问令牌(Access Token)传递。它被客户端用来访问受保护的资源。

2. 实现 OAuth 2.0 授权流程

在本节中,我们将使用 FastAPI 实现 OAuth 2.0 授权流程,并使用 JWT 进行认证。我们将使用 GitHub 作为 OAuth 提供者进行演示。

2.1 安装必要的依赖

首先,我们需要安装 fastapihttpx(用于异步 HTTP 请求)以及 python-dotenv(用于加载环境变量)。


pip install fastapi httpx python-dotenv

2.2 创建 GitHub OAuth 2.0 应用

在 GitHub 上注册 OAuth 应用:

  1. 访问 GitHub 开发者设置页面:GitHub Developer Settings
  2. 创建一个新的 OAuth 应用,记录下 Client IDClient Secret

将这些凭据存储在 .env 文件中:

GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
GITHUB_REDIRECT_URI=http://localhost:8000/callback

2.3 FastAPI 实现 OAuth 2.0 授权流程

以下是一个简单的 FastAPI 应用,实现 GitHub OAuth 2.0 授权流程,并使用 JWT 生成用户的认证令牌。

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from fastapi.responses import RedirectResponse
import httpx
import jwt
import os
from dotenv import load_dotenv

load_dotenv()

app = FastAPI()

# 配置环境变量
CLIENT_ID = os.getenv("GITHUB_CLIENT_ID")
CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET")
REDIRECT_URI = os.getenv("GITHUB_REDIRECT_URI")
GITHUB_API_URL = "https://api.github.com/user"

# JWT 配置
SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"

# OAuth 2.0 URL
AUTH_URL = f"https://github.com/login/oauth/authorize?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}"

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


# 路由:重定向到 GitHub 授权页面
@app.get("/login")
async def login():
    return RedirectResponse(url=AUTH_URL)


# 路由:GitHub 回调并获取用户信息
@app.get("/callback")
async def callback(code: str):
    # 获取 GitHub 返回的 `code`,用它请求 `access_token`
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://github.com/login/oauth/access_token",
            data={
                "client_id": CLIENT_ID,
                "client_secret": CLIENT_SECRET,
                "code": code,
                "redirect_uri": REDIRECT_URI,
            },
            headers={"Accept": "application/json"},
        )
    
    data = response.json()
    access_token = data.get("access_token")

    if not access_token:
        raise HTTPException(status_code=400, detail="GitHub authorization failed")

    # 使用 Access Token 获取 GitHub 用户信息
    async with httpx.AsyncClient() as client:
        user_info = await client.get(
            GITHUB_API_URL,
            headers={"Authorization": f"Bearer {access_token}"}
        )

    user = user_info.json()
    
    # 生成 JWT 令牌
    jwt_token = jwt.encode({"sub": user["login"]}, SECRET_KEY, algorithm=ALGORITHM)

    return {"access_token": jwt_token, "token_type": "bearer"}


# 路由:受保护的资源,只有认证用户可以访问
@app.get("/protected")
async def protected(token: str = Depends(oauth2_scheme)):
    try:
        # 解码 JWT,验证身份
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        user = payload.get("sub")
        if user is None:
            raise HTTPException(status_code=403, detail="Could not validate credentials")
        return {"message": f"Welcome, {user}!"}
    except jwt.PyJWTError:
        raise HTTPException(status_code=403, detail="Could not validate credentials")

2.4 流程解释

  1. 用户登录:访问 /login 路由,用户将被重定向到 GitHub 的 OAuth 授权页面。
  2. 用户授权:用户在 GitHub 页面同意授权后,GitHub 会回调 /callback 路由,并附带一个 code
  3. 交换授权码:FastAPI 会使用 code 向 GitHub 请求 access_token
  4. 获取用户信息:使用 access_token 获取用户信息。
  5. 生成 JWT:使用用户的 GitHub 登录名生成 JWT 令牌,并返回给客户端。
  6. 访问受保护资源:客户端可以使用该 JWT 访问受保护资源。FastAPI 会验证 JWT 是否有效,并返回用户的信息。

通过使用 FastAPI,我们成功实现了 OAuth 2.0 授权流程与 JWT 集成。FastAPI 提供了简单且强大的工具来处理 OAuth 2.0 授权,快速构建安全的 API。我们通过以下方式实现了 API 安全认证:

  • 使用 GitHub 作为 OAuth 2.0 提供者进行用户认证。
  • 使用 JWT 作为认证令牌,确保 API 安全。
  • 利用 FastAPI 的简洁语法快速集成认证流程和安全功能。

这种方法可以很容易地扩展到其他 OAuth 2.0 提供者(如 Google、Facebook 等),并且 FastAPI 的异步特性使得这一过程非常高效。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值