廣州做網(wǎng)站建設(shè)哪家專業(yè)網(wǎng)站關(guān)鍵詞怎么設(shè)置
FastAPI:Token認(rèn)證
本教程通過 FastAPI 實(shí)現(xiàn)用戶登錄和基于 JWT(JSON Web Token) 的認(rèn)證與授權(quán),適合初學(xué)者到進(jìn)階用戶。教程特別關(guān)注 Depends
、OAuth2PasswordBearer
等非基礎(chǔ)操作的詳細(xì)講解,幫助你全面掌握相關(guān)技術(shù)。
環(huán)境準(zhǔn)備
首先,確保安裝必要的依賴庫:
pip install fastapi uvicorn PyJWT
什么是 JWT
JWT (JSON Web Token) 是一種輕量級(jí)的認(rèn)證機(jī)制,常用于客戶端與服務(wù)器之間的通信。它主要包含三部分:
- Header:算法與類型。
- Payload:包含用戶信息及聲明。
- Signature:用于校驗(yàn)數(shù)據(jù)完整性。
JWT 示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJ1c2VyMSIsImV4cCI6MTY5MjMyMzAwMH0
.Wu6HB7pCDHgVvmD3_a8Ev9fGzY1Kc0FnVmCvO1Wl1qM
用戶登錄的基礎(chǔ)實(shí)現(xiàn)
創(chuàng)建一個(gè)簡單的用戶登錄接口,驗(yàn)證用戶名和密碼。首先實(shí)現(xiàn)模擬的用戶數(shù)據(jù)庫和基本的登錄驗(yàn)證:
from fastapi import FastAPI, HTTPException
from fastapi.security import OAuth2PasswordRequestFormapp = FastAPI()# 模擬用戶數(shù)據(jù)庫
USERS_DB = {"admin": "password123","user": "mypassword"
}@app.post("/login")
async def login(form_data: OAuth2PasswordRequestForm):"""登錄接口,驗(yàn)證用戶名和密碼是否匹配。"""username = form_data.usernamepassword = form_data.passwordif username not in USERS_DB or USERS_DB[username] != password:raise HTTPException(status_code=401, detail="用戶名或密碼錯(cuò)誤")return {"message": f"歡迎回來,{username}!"}
啟動(dòng)服務(wù):
uvicorn main:app --reload
訪問 http://127.0.0.1:8000/docs,測試 /login
接口。
JWT 的生成與驗(yàn)證
引入 PyJWT 生成令牌。我們將為成功登錄的用戶生成一個(gè)包含身份信息和過期時(shí)間的 JWT。
import jwt
import datetimeSECRET_KEY = "your_secret_key" # 替換為你的密鑰
ALGORITHM = "HS256" # 簽名算法
TOKEN_EXPIRE_HOURS = 1 # 令牌有效時(shí)間(小時(shí))def create_jwt(username: str) -> str:"""生成 JWT。"""payload = {"sub": username, # 用戶名"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=TOKEN_EXPIRE_HOURS) # 過期時(shí)間}return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)@app.post("/login")
async def login(form_data: OAuth2PasswordRequestForm):"""登錄接口:驗(yàn)證用戶名密碼并返回 JWT。"""username = form_data.usernamepassword = form_data.passwordif username not in USERS_DB or USERS_DB[username] != password:raise HTTPException(status_code=401, detail="用戶名或密碼錯(cuò)誤")token = create_jwt(username)return {"access_token": token, "token_type": "bearer"}
FastAPI 的認(rèn)證工具
什么是 Depends
Depends
是 FastAPI 中的依賴注入工具,用于在路由中動(dòng)態(tài)引入邏輯。例如,可以通過它獲取登錄用戶的 Token,或者驗(yàn)證 Token 的合法性。
什么是 OAuth2PasswordBearer
OAuth2PasswordBearer
是 FastAPI 提供的一個(gè)工具,幫助我們解析 Bearer Token。它會(huì)從請(qǐng)求頭的 Authorization
字段中提取 Token。
使用示例
from fastapi.security import OAuth2PasswordBeareroauth2_scheme = OAuth2PasswordBearer(tokenUrl="login") # 指定獲取 Token 的登錄端點(diǎn)
- 當(dāng)我們?cè)诼酚芍幸蕾?
oauth2_scheme
時(shí),它會(huì)自動(dòng)解析 Token,并作為參數(shù)傳遞給路由函數(shù)。
實(shí)現(xiàn)受保護(hù)路由和 Token 驗(yàn)證
我們?cè)谶@里驗(yàn)證 Token 的有效性,并返回用戶信息。
from fastapi import Dependsdef decode_jwt(token: str):"""驗(yàn)證并解碼 JWT。"""try:payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])return payloadexcept jwt.ExpiredSignatureError:raise HTTPException(status_code=401, detail="令牌已過期")except jwt.InvalidTokenError:raise HTTPException(status_code=401, detail="令牌無效")@app.get("/protected")
async def protected_route(token: str = Depends(oauth2_scheme)):"""受保護(hù)的路由,需提供有效 JWT。"""payload = decode_jwt(token)username = payload.get("sub")if not username:raise HTTPException(status_code=401, detail="令牌無效")return {"message": f"歡迎回來,{username}!這是一個(gè)受保護(hù)的路由。"}
- 使用
/login
接口獲取 Token。 - 訪問
/protected
,并在Authorization
請(qǐng)求頭中添加Bearer <your_token>
。
優(yōu)化代碼結(jié)構(gòu)(解耦與擴(kuò)展)
為了更好的維護(hù)和擴(kuò)展,將用戶管理和 JWT 邏輯拆分到獨(dú)立模塊中。
# services/user_service.py
class UserService:"""用戶服務(wù)類:處理用戶驗(yàn)證。"""def __init__(self):self.users_db = {"admin": "password123","user": "mypassword"}def authenticate(self, username: str, password: str) -> bool:"""驗(yàn)證用戶名和密碼是否匹配。"""return self.users_db.get(username) == password
import jwt
import datetime
from fastapi import HTTPExceptionclass JWTHandler:"""JWT 工具類:負(fù)責(zé)生成和驗(yàn)證 JWT。"""SECRET_KEY = "your_secret_key"ALGORITHM = "HS256"@staticmethoddef create_token(username: str) -> str:payload = {"sub": username,"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)}return jwt.encode(payload, JWTHandler.SECRET_KEY, algorithm=JWTHandler.ALGORITHM)@staticmethoddef decode_token(token: str):try:return jwt.decode(token, JWTHandler.SECRET_KEY, algorithms=[JWTHandler.ALGORITHM])except jwt.ExpiredSignatureError:raise HTTPException(status_code=401, detail="令牌已過期")except jwt.InvalidTokenError:raise HTTPException(status_code=401, detail="令牌無效")
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from user_service import UserService
from jwt_handler import JWTHandlerapp = FastAPI()
user_service = UserService()
jwt_handler = JWTHandler()oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")@app.post("/login")
async def login(form_data:OAuth2PasswordRequestForm = Depends()):if not user_service.verify_user(form_data.username, form_data.password):raise HTTPException(status_code=401, detail="用戶名或密碼錯(cuò)誤")token = jwt_handler.create_token(form_data.username)return {"access_token": token, "token_type": "bearer"}@app.get("/protected")
async def protected_route(token: str = Depends(oauth2_scheme)):payload = jwt_handler.decode_token(token)username = payload.get("sub")return {"message": f"歡迎回來,{username}!"}if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)
總結(jié)
通過本教程,你學(xué)會(huì)了:
- 基于 FastAPI 實(shí)現(xiàn)用戶登錄和 JWT Token 認(rèn)證。
- 使用
Depends
和OAuth2PasswordBearer
實(shí)現(xiàn)認(rèn)證邏輯。 - 解耦代碼結(jié)構(gòu),提升可擴(kuò)展性。
可以進(jìn)一步擴(kuò)展功能,比如引入數(shù)據(jù)庫存儲(chǔ)用戶信息或添加刷新 Token 的機(jī)制。