如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?
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() 函数接收权限验证依赖项,验证流程如下:
- 客户端发送携带凭证的请求
- 依赖项解析 JWT 令牌或 API Key
- 验证凭证有效性,提取用户角色
- 根据角色判断是否允许访问该端点
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"
}
分析步骤:
- 检查用户角色分配是否正确
- 验证权限依赖项是否正确定义
- 测试直接调用权限验证函数
4.2 安全加固最佳实践
- 使用 HTTPS 加密所有通信
- 令牌设置合理有效期(JWT 的 exp 声明)
- 敏感操作记录审计日志
课后 Quiz
如何测试用户权限升级场景?
A) 修改数据库角色字段
B) 使用权限验证函数的 mock 对象
C) 直接修改 JWT 令牌内容收到 422 Unprocessable Entity 错误应首先检查?
A) 服务器防火墙设置
B) 请求体数据格式
C) 数据库连接状态
答案解析:
- 正确答案 B。通过 mock 返回不同角色用户对象,避免直接操作数据库或令牌
- 正确答案 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中打造一个既安全又灵活的权限管理系统? | cmdragon's Blog
- FastAPI访问令牌的权限声明与作用域管理:你的API安全真的无懈可击吗? | cmdragon's Blog
- 如何在FastAPI中构建一个既安全又灵活的多层级权限系统? | cmdragon's Blog
- FastAPI如何用角色权限让Web应用安全又灵活? | cmdragon's Blog
- FastAPI权限验证依赖项究竟藏着什么秘密? | cmdragon's Blog
- 如何用FastAPI和Tortoise-ORM打造一个既高效又灵活的角色管理系统? | cmdragon's Blog
- JWT令牌如何在FastAPI中实现安全又高效的生成与验证? | cmdragon's Blog
- 你的密码存储方式是否在向黑客招手? | cmdragon's Blog
- 如何在FastAPI中轻松实现OAuth2认证并保护你的API? | cmdragon's Blog
- FastAPI安全机制:从OAuth2到JWT的魔法通关秘籍 | cmdragon's Blog
- FastAPI认证系统:从零到令牌大师的奇幻之旅 | cmdragon's Blog
- FastAPI安全异常处理:从401到422的奇妙冒险 | cmdragon's Blog
- FastAPI权限迷宫:RBAC与多层级依赖的魔法通关秘籍 | cmdragon's Blog
- JWT令牌:从身份证到代码防伪的奇妙之旅 | cmdragon's Blog
- FastAPI安全认证:从密码到令牌的魔法之旅 | cmdragon's Blog
- 密码哈希:Bcrypt的魔法与盐值的秘密 | cmdragon's Blog
- 用户认证的魔法配方:从模型设计到密码安全的奇幻之旅 | cmdragon's Blog
- FastAPI安全门神:OAuth2PasswordBearer的奇妙冒险 | cmdragon's Blog
- OAuth2密码模式:信任的甜蜜陷阱与安全指南 | cmdragon's Blog
- API安全大揭秘:认证与授权的双面舞会 | cmdragon's Blog
- 异步日志监控:FastAPI与MongoDB的高效整合之道 | cmdragon's Blog
- FastAPI与MongoDB分片集群:异步数据路由与聚合优化 | cmdragon's Blog
- FastAPI与MongoDB Change Stream的实时数据交响曲 | cmdragon's Blog
- 地理空间索引:解锁日志分析中的位置智慧 | cmdragon's Blog
- 异步之舞:FastAPI与MongoDB的极致性能优化之旅 | cmdragon's Blog
- 异步日志分析:MongoDB与FastAPI的高效存储揭秘 | cmdragon's Blog
- MongoDB索引优化的艺术:从基础原理到性能调优实战 | cmdragon's Blog
- 解锁FastAPI与MongoDB聚合管道的性能奥秘 | cmdragon's Blog
- 异步之舞:Motor驱动与MongoDB的CRUD交响曲 | cmdragon's Blog
- 异步之舞:FastAPI与MongoDB的深度协奏 | cmdragon's Blog
- 数据库迁移的艺术:FastAPI生产环境中的灰度发布与回滚策略 | cmdragon's Blog
- 数据库迁移的艺术:团队协作中的冲突预防与解决之道 | cmdragon's Blog
- 驾驭FastAPI多数据库:从读写分离到跨库事务的艺术 | cmdragon's Blog
- 数据库事务隔离与Alembic数据恢复的实战艺术 | cmdragon's Blog
- FastAPI与Alembic:数据库迁移的隐秘艺术 | cmdragon's Blog
- 飞行中的引擎更换:生产环境数据库迁移的艺术与科学 | cmdragon's Blog
- Alembic迁移脚本冲突的智能检测与优雅合并之道 | cmdragon's Blog
- XML Sitemap
如何在FastAPI中玩转权限控制与测试,让代码安全又优雅?的更多相关文章
- (转)浅析Java中的访问权限控制
原文地址: http://www.cnblogs.com/dolphin0520/p/3734915.html 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下 ...
- 浅析Java中的访问权限控制
浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...
- IOS中实例的权限控制
@public.@protected.@private的使用 在OC中声明一个类的时候,可以使用上面 @public.@protected.@private三个关键字声明实例的权限,例如下面的代码: ...
- .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理
.NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...
- 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。
[TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...
- Java中的访问权限控制
Java提供了public, private, protected 三个访问权限修饰词,提供了以下四种访问权限控制机制: 1.包访问权限: 2.Public访问权限: 3.Private访问权限: 4 ...
- WPF wpf中按钮操作权限控制
权限控制我们有很多种方式可以实现. 这次项目中做个简单的权限控制,我们在所有按钮触发前判断,有权限则可执行. 我们自定义一个命令类. public class DelegateCommand : IC ...
- pc vue 项目中的菜单权限控制
在pc 管理系统这种类型的产品,通常会涉及到账号权限的控制,不同的账号权限能浏览的功能模块是不同的,对应侧边栏菜单模块的显示也会不同. 场景一.(电商类管理系统) 登录 登录后,依次获取账号 toke ...
- ThinkPHP中:RBAC权限控制的实习步骤
使用版本ThinkPHP3.1.3 第一步,建表及数据 第二步,建关联模型 第三步,控制器使用关联模型.配置文件 第四步,模板显示数据 第一步,建表及数据 在数据库中,建立一个companysvn数据 ...
- 在PyCharm中以root权限运行和调试python代码
python中有的代码可能需要su权限,如 import os os.mkdir('/media/xxx/disk_a') 如果在交互式环境中使用,需要以sudo的方式启动python.而在PyCha ...
随机推荐
- 关于普通程序员该如何参与AI学习的三个建议以及自己的实践
大部分程序员在学习大语言模型的时候都比较痛苦,感觉AI是如此之近又如此之远,仿佛能搞明白一点,又好像什么也没明白.就像我们在很远的地方看珠穆拉玛峰,感觉它就像一个不大的山包,感觉只要自己做足准备咬咬牙 ...
- 堆排序(标准版)(NB)
博客地址:https://www.cnblogs.com/zylyehuo/ # _*_coding:utf-8_*_ import random def sift(li, low, high): # ...
- 系统自带模版在 emlog pro 1.8.0 底部信息错位问题暂时的解决方案
问题描述 作为一名 emlog 爱好者,笔者闲暇时间经常为 emlog 系统的 Github 仓库里( https://github.com/emlog/emlog )提 pr 和修修补补,就像其他知 ...
- PostgreSQL 密码忘了
许久不登, 倒是把默认的 postgres 用户的密码给忘了... 首先关闭 PostgreSQL. 我这是 Windows 上安装的, 所以到服务 (services.msc) 里关闭. 然后修改配 ...
- JSON Objects Framework(1)
学习datasnap,json必须掌握.用自身的JSON,就必须熟悉JSON Objects Framework.其中tostring和value区别就是一个坑. The JSON objects f ...
- 卸载重装vscode
最近工作需要长期用到python,但我的老电脑又实在拉不起pycharm那配置,干脆就用vscode了,但本来我的vscode是用来写c/c++的,安装配置一通乱搞,现在也不知道怎么配置回来了. 干脆 ...
- JSON对象、JSON字符串和Java对象互相转
JSON对象.JSON字符串和Java对象互相转 Java对象转json字符串(一般使用字符串存储redis或者数据库) public static String toJSONString(Objec ...
- 在web.xml下配置springmvc的核心控制器
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" ...
- 多线程的waiting与notify
一.waiting()与notify() /* 进入到TimeWaiting(计时等待)有两种方式 1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Block ...
- python批量检测链接是否可正常打开
通过一些爬虫脚本爬取图站图片,但是发现有些图片是没法打开的,可能返回404的code码 所以设计一个脚本,对所有的图片地址进行检查,返回200的保存到另外一个文本内,然后再去下载 脚本逻辑很简单,直接 ...