title: 如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?
date: 2025/06/18 10:11:53
updated: 2025/06/18 10:11:53
author: cmdragon
excerpt:
FastAPI通过依赖注入系统实现权限控制,使用Depends()
函数接收权限验证依赖项,验证流程包括解析凭证、验证有效性并提取用户角色。权限层级划分为公共端点、用户级端点和管理员端点。单元测试使用pytest
验证权限逻辑,集成测试通过httpx
模拟请求。完整测试案例包括用户系统权限测试和覆盖率提升技巧。常见问题如401和403错误,解决方案包括检查请求头和用户角色分配。安全加固建议使用HTTPS、设置令牌有效期和记录审计日志。
categories:
tags:
扫描二维码
关注或者微信搜一搜:编程智域 前端至全栈交流与成长
发现1000+提升效率与开发的AI工具和实用程序:https://tools.cmdragon.cn/
FastAPI 采用依赖注入系统(Dependency Injection)实现权限控制。每个路由通过 Depends()
函数接收权限验证依赖项,验证流程如下:
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"}
根据业务需求设计权限层级:
/public
)/user/profile
)/admin/dashboard
)使用 pytest
直接测试权限验证函数:
# 测试文件 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
使用 httpx
模拟不同角色用户的请求:
# 测试文件 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
生成覆盖率报告pytest --cov=app --cov-report=html tests/
问题 1:401 Unauthorized
{
"detail": "Not authenticated"
}
原因:
解决:
# 正确请求头示例
headers = {
"Authorization": "Bearer admin_token"
}
问题 2:403 Forbidden
{
"detail": "Insufficient permissions"
}
分析步骤:
如何测试用户权限升级场景?
A) 修改数据库角色字段
B) 使用权限验证函数的 mock 对象
C) 直接修改 JWT 令牌内容
收到 422 Unprocessable Entity 错误应首先检查?
A) 服务器防火墙设置
B) 请求体数据格式
C) 数据库连接状态
答案解析:
运行环境配置:
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
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
,阅读完整的文章:如何在FastAPI中玩转权限控制与测试,让代码安全又优雅? | cmdragon's Blog
参与评论
手机查看
返回顶部