Skip to content

32. FastAPI 依赖注入_路由级 ​

为整个 APIRouter 统一附加依赖 ​

后台管理下的十几个接口都要相同检查时,在每个装饰器上重复填写容易漏写。路由级依赖可以绑定到一个 APIRouter,或在 include_router 时追加,覆盖该路由集合的操作。

最小完整示例 ​

python
from typing import Annotated
from fastapi import APIRouter, Depends, FastAPI, Header, HTTPException

app = FastAPI()

def check_admin_demo(
    x_study_role: Annotated[str | None, Header()] = None,
):
    if x_study_role != "admin":
        raise HTTPException(403, "需要管理员权限")

admin = APIRouter(prefix="/admin", tags=["管理"],
                  dependencies=[Depends(check_admin_demo)])

@admin.get("/users")
def users():
    return [{"id": 1, "name": "小明"}]

@admin.get("/reports")
def reports():
    return {"count": 10}

@app.get("/public")
def public():
    return {"message": "公开"}

app.include_router(admin, prefix="/api/v1")

保存为 main.py 并启动。访问 /api/v1/admin/users 和 /api/v1/admin/reports 都需要 X-Study-Role: admin;/public 不需要。

这个头仅用于观察依赖覆盖范围,客户端可以任意伪造,不能用于真实管理员判定。实际角色应在验证令牌后从服务端可信用户资料中读取,第 36 篇介绍认证基础。

两个配置位置有什么区别 ​

在 APIRouter(dependencies=...) 设置,代表路由自身的共同要求;在 app.include_router(router, dependencies=...) 设置,代表这次挂载额外附加的要求。模块路由被不同应用复用时,后者更灵活。

依赖是叠加而不是覆盖:全局要求、路由要求、单操作要求都会参与执行。想为某一条操作取消路由级认证,通常应把它拆到独立的公开路由集合,而不是在函数里试图跳过已经执行的依赖。

返回值和组织方式 ​

路由级依赖的返回值也不会自动注入函数。需要当前用户时,在具体函数中声明同一用户依赖;同一请求通常可复用缓存结果。认证、角色检查可以按嵌套依赖组织,避免重复解码令牌。

业务 tags、路径前缀都只是组织手段,没有默认的安全效果;真正控制权限的是执行的认证和授权逻辑。

练习:把 /admin/reports 拆到单独的只读路由,给它增加另一项依赖;列出每个最终 URL 会执行哪些检查。