FastAPI端点角色访问控制:如何将装饰器角色传入Depends方法
FastAPI 基于角色的访问控制实现方案
方案一:用带参数的依赖工厂(推荐)
不需要额外装饰器,直接让依赖项支持动态传入角色,完美适配FastAPI的Depends机制:
步骤1:编写带角色参数的依赖工厂函数
from fastapi import Depends, HTTPException, status def get_current_user_with_role(required_role: str): async def dependency(): # 1. 获取当前用户(示例:从请求头解析token等逻辑) user = await fetch_current_user_from_request() if not user: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="未认证") # 2. 调用授权服务验证角色匹配 is_authorized = await auth_service.verify_user_role(user.id, required_role) if not is_authorized: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="权限不足") return user.id return dependency
步骤2:在路由中直接使用该依赖
@router.get('/') async def get_items(user_id: str = Depends(get_current_user_with_role("admin"))): return await get_all_items()
这个方案的优势:
- 逻辑直接,依赖本身明确声明所需角色,可读性强
- 天然利用FastAPI Depends的请求级缓存,无需额外处理
- 易于扩展支持多角色(比如把参数改成
required_roles: list[str],验证时检查用户是否拥有其中任一角色)
方案二:装饰器+读取路由元数据(兼容原有装饰器写法)
如果一定要保留装饰器标记角色的方式,可以把角色存入路由端点的元数据中,再在依赖里读取:
步骤1:编写角色装饰器,存储角色到路由元数据
def roles_decorator(required_role: str): def decorator(func): # 将角色存入函数的自定义属性,后续从请求上下文读取 setattr(func, "_required_role", required_role) return func return decorator
步骤2:修改get_current_user,从请求上下文获取角色
from fastapi import Request async def get_current_user(request: Request): # 获取当前路由对应的端点函数 endpoint = request.scope.get("endpoint") required_role = getattr(endpoint, "_required_role", None) if not required_role: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="未配置所需角色") # 后续认证&角色验证逻辑和方案一一致 user = await fetch_current_user_from_request() if not user: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="未认证") is_authorized = await auth_service.verify_user_role(user.id, required_role) if not is_authorized: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="权限不足") return user.id
步骤3:路由写法保持不变
@router.get('/') @roles_decorator("admin") async def get_items(user_id: str = Depends(get_current_user)): return await get_all_items()
这个方案注意点:
- 依赖于FastAPI的请求上下文结构,若框架版本更新可能需要调整
- 适合需要统一用装饰器标记权限的场景,但可读性略低于方案一
内容的提问来源于stack exchange,提问作者cole
相关产品推荐
相关产品推荐

