如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?
title: 如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?

from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import OAuth2PasswordBearer
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# 角色权限校验函数
async def verify_admin(token: str = Depends(oauth2_scheme)):
if token != "admin_token": # 模拟验证逻辑
raise HTTPException(status_code=403, detail="Not authorized")
return {"role": "admin"}
# 受保护端点
@app.get("/admin")
async def admin_route(user: dict = Depends(verify_admin)):
return {"message": "Admin access granted"}
# 测试文件 test_security.py
from fastapi import HTTPException
import pytest
async def test_admin_verification_success():
# 正确令牌测试
result = await verify_admin("admin_token")
assert result["role"] == "admin"
async def test_admin_verification_failure():
# 错误令牌测试
with pytest.raises(HTTPException) as exc:
await verify_admin("invalid_token")
assert exc.value.status_code == 403
# 测试文件 test_routes.py
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_public_access():
response = client.get("/public")
assert response.status_code == 200
def test_admin_access_denied():
# 普通用户访问管理员端点
response = client.get("/admin", headers={"Authorization": "Bearer user_token"})
assert response.status_code == 403
assert "Not authorized" in response.json()["detail"]
# 文件结构
# ├── main.py
# ├── security.py
# └── tests/
# ├── conftest.py
# ├── test_security.py
# └── test_routes.py
# security.py 扩展版
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
username: str
role: Optional[str] = "user"
async def get_current_user(token: str = Depends(oauth2_scheme)):
# 模拟数据库查询
users = {
"user_token": User(username="john", role="user"),
"admin_token": User(username="admin", role="admin")
}
if token not in users:
raise HTTPException(status_code=401, detail="Invalid token")
return users[token]
def check_role(required_role: str):
async def role_checker(user: User = Depends(get_current_user)):
if user.role != required_role:
raise HTTPException(status_code=403, detail="Insufficient permissions")
return Depends(role_checker)
pytest --cov=app --cov-report=html tests/
{
"detail": "Not authenticated"
}
# 正确请求头示例
headers = {
"Authorization": "Bearer admin_token"
}
{
"detail": "Insufficient permissions"
}
pip install fastapi==0.68.0 uvicorn==0.15.0 pydantic==1.10.7
pip install pytest==6.2.5 httpx==0.19.0 pytest-cov==3.0.0
评论
发表评论