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:

  • 后端开发
  • FastAPI

tags:

  • FastAPI
  • 权限控制
  • 依赖注入
  • 单元测试
  • 集成测试
  • JWT
  • 安全加固

扫描二维码

关注或者微信搜一搜:编程智域 前端至全栈交流与成长

发现1000+提升效率与开发的AI工具和实用程序https://tools.cmdragon.cn/

一、FastAPI 权限控制基础实现

1.1 权限控制核心原理

FastAPI 采用依赖注入系统(Dependency Injection)实现权限控制。每个路由通过 Depends() 函数接收权限验证依赖项,验证流程如下:

  1. 客户端发送携带凭证的请求
  2. 依赖项解析 JWT 令牌或 API Key
  3. 验证凭证有效性,提取用户角色
  4. 根据角色判断是否允许访问该端点
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"}

1.2 权限层级划分策略

根据业务需求设计权限层级:

  • 公共端点:无需认证(如 /public
  • 用户级端点:需有效令牌(如 /user/profile
  • 管理员端点:需管理员角色(如 /admin/dashboard

二、权限测试核心策略

2.1 单元测试验证权限逻辑

使用 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

2.2 集成测试模拟完整请求流

使用 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"]

三、完整测试案例解析

3.1 用户系统权限测试实现

构建包含多角色的用户管理系统:

# 文件结构
# ├── 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)

3.2 测试覆盖率提升技巧

  • 使用 pytest-cov 生成覆盖率报告
pytest --cov=app --cov-report=html tests/
  • 覆盖所有权限分支场景:

    • 合法令牌+正确角色
    • 合法令牌+错误角色
    • 无效令牌
    • 缺失认证头

四、常见问题解决方案

4.1 典型报错处理

问题 1:401 Unauthorized

{
"detail": "Not authenticated"
}

原因

  • 请求未携带 Authorization 头
  • 令牌格式错误(如缺少 Bearer 前缀)

解决

# 正确请求头示例
headers = {
"Authorization": "Bearer admin_token"
}

问题 2:403 Forbidden

{
"detail": "Insufficient permissions"
}

分析步骤

  1. 检查用户角色分配是否正确
  2. 验证权限依赖项是否正确定义
  3. 测试直接调用权限验证函数

4.2 安全加固最佳实践

  1. 使用 HTTPS 加密所有通信
  2. 令牌设置合理有效期(JWT 的 exp 声明)
  3. 敏感操作记录审计日志

课后 Quiz

  1. 如何测试用户权限升级场景?

    A) 修改数据库角色字段

    B) 使用权限验证函数的 mock 对象

    C) 直接修改 JWT 令牌内容

  2. 收到 422 Unprocessable Entity 错误应首先检查?

    A) 服务器防火墙设置

    B) 请求体数据格式

    C) 数据库连接状态

答案解析

  1. 正确答案 B。通过 mock 返回不同角色用户对象,避免直接操作数据库或令牌
  2. 正确答案 B。422 错误通常表示请求体不符合 Pydantic 模型验证规则

运行环境配置

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

往期文章归档:

如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?的更多相关文章

  1. (转)浅析Java中的访问权限控制

    原文地址: http://www.cnblogs.com/dolphin0520/p/3734915.html 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下 ...

  2. 浅析Java中的访问权限控制

    浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...

  3. IOS中实例的权限控制

    @public.@protected.@private的使用 在OC中声明一个类的时候,可以使用上面 @public.@protected.@private三个关键字声明实例的权限,例如下面的代码: ...

  4. .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理

    .NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...

  5. 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。

    [TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...

  6. Java中的访问权限控制

    Java提供了public, private, protected 三个访问权限修饰词,提供了以下四种访问权限控制机制: 1.包访问权限: 2.Public访问权限: 3.Private访问权限: 4 ...

  7. WPF wpf中按钮操作权限控制

    权限控制我们有很多种方式可以实现. 这次项目中做个简单的权限控制,我们在所有按钮触发前判断,有权限则可执行. 我们自定义一个命令类. public class DelegateCommand : IC ...

  8. pc vue 项目中的菜单权限控制

    在pc 管理系统这种类型的产品,通常会涉及到账号权限的控制,不同的账号权限能浏览的功能模块是不同的,对应侧边栏菜单模块的显示也会不同. 场景一.(电商类管理系统) 登录 登录后,依次获取账号 toke ...

  9. ThinkPHP中:RBAC权限控制的实习步骤

    使用版本ThinkPHP3.1.3 第一步,建表及数据 第二步,建关联模型 第三步,控制器使用关联模型.配置文件 第四步,模板显示数据 第一步,建表及数据 在数据库中,建立一个companysvn数据 ...

  10. 在PyCharm中以root权限运行和调试python代码

    python中有的代码可能需要su权限,如 import os os.mkdir('/media/xxx/disk_a') 如果在交互式环境中使用,需要以sudo的方式启动python.而在PyCha ...

随机推荐

  1. 搭建自己的OCR服务,第一步:选择合适的开源OCR项目

    一.OCR是什么? 光学字符识别(Optical Character Recognition, OCR)是指对文本资料的图像文件进行分析识别处理,获取文字及版面信息的过程. 亦即将图像中的文字进行识别 ...

  2. 【虚拟机】Windows(x86)上部署ARM虚拟机(Ubuntu)

    [虚拟机]Windows(x86)上部署ARM虚拟机(Ubuntu) 零.起因 最近在学嵌入式,这就不得不涉及ARM指令集,但是电脑是x86指令集的,用手机不太方便,买开发板又要等几天--,总之就是要 ...

  3. 【Guava】集合工具类-Immutable&Lists&Maps&Sets

    Immutable 如<Effective Java>Item1)所述,在设计类的时候,倾向优先使用静态工厂方法(static factory method)而非构造函数(construc ...

  4. DEF4Delphi-master的安装

    保姆教程 d2007的TWEBbrowser因为用的太老的IE内核.现在的浏览器上的功能呈现就卡住了. 那么DEF4Delphi效果非常好. 如何安装后成功运行.很简单.直接去:https://git ...

  5. 《Python基础教程》第三版语录

    对程序的结构(如需要哪些类和函数)有一定的想法后,建议你实现一个功能可能极其有限的简单版本. 当你有了可运行的程序后,将发现接下来的工作容易得多.你可添加新功能,修改不喜欢的方面,等等.这样你才能够真 ...

  6. 支付宝当面付和微信付款码支付封装DLL

    项目中需要为客户对接支付宝的当面付和微信付款码支付.场景就是软件中生成金额订单,然后扫顾客的微信付款码或者支付宝的付款码完成收款.为此封装了此DLL,可以用在其他项目中,其他人也可以直接拿来用. 最主 ...

  7. 从源码解析 QGraphicsItem 旋转、缩放、平移、transform等变换操作,利用QGraphicsTransform实现变形动画

    QGraphicsItem 有3种方式进行变换:1. 最简单方便的是使用 setRotation() .setScale():2. 使用 setTransform() 进行复杂变换:3. 还可以使用 ...

  8. C++宏定义中可变参数列表__VA_ARGS__ 及 QT 提供的宏 QT_OVERLOADED_MACRO

    1. 基本用法 VA_ARGS 是 C/C++ 中的预定义宏,用于在宏定义中表示可变参数列表(Variadic Arguments),需与省略号 ... 配合使用.其核心作用是将宏调用中的可变参数原样 ...

  9. Python科学计算系列6—积分

    1.定积分 例1:求下列函数的定积分 代码如下: from sympy import * x = symbols('x') f = integrate(exp(-x), (x, 0, oo)) pri ...

  10. 解决github页面打不开 页面加载慢,注册不了显示Unable to verify your captcha response...

    解决国内打开Github页面.注册等问题 下列方法可以解决: github网站页面打不开: github页面打开慢,偶尔打不开,部分页面链接也打不开: 注册不了github账号,找回密码失败等,显示U ...