大数跨境
0
0

FastAPI 入门教程 #16:使用依赖项实现权限控制

FastAPI 入门教程 #16:使用依赖项实现权限控制 人人都懂物联网
2025-06-29
0
导读:在构建 API 应用时,你不仅需要验证用户身份(认证),还要控制他们是否有权限访问特定资源(授权)。本文将介绍如何利用 FastAPI 的 依赖项机制 实现权限控制,例如仅允许管理员访问某些接口等。

 

 

在构建 API 应用时,你不仅需要验证用户身份(认证),还要控制他们是否有权限访问特定资源(授权)。本文将介绍如何利用 FastAPI 的 依赖项机制(dependency injection) 实现权限控制,例如仅允许管理员访问某些接口等。你将学会自定义权限依赖项并在路由中灵活使用。

权限控制简介

权限控制(Authorization) 是判断用户是否有权访问某个资源或操作的过程。例如:

  • • 普通用户只能查看自己的信息;
  • • 管理员可以查看所有用户信息;
  • • 某些接口仅限特定角色调用。

FastAPI 没有内置“角色权限系统”,但你可以使用依赖项来灵活实现这些功能。

实现思路

  • • 用户登录后通过 JWT 获取身份信息;
  • • 在 JWT 的 payload 中添加用户角色(如 adminuser);
  • • 创建依赖项函数判断当前用户的权限;
  • • 将依赖项添加到需要权限控制的路由中。

示例代码

假设你已经完成了用户认证和 JWT 登录(见前文教程),我们在此基础上添加权限控制逻辑。

1. 用户模拟数据(users.py)

fake_users_db = {
    "alice": {
        "username""alice",
        "hashed_password""$2b$12$...",
        "role""user"
    },
    "bob": {
        "username""bob",
        "hashed_password""$2b$12$...",
        "role""admin"
    }
}

2. 修改 token 签发逻辑(auth.py)

def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta or timedelta(minutes=30))
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

在登录逻辑中添加用户角色到 payload:

# 登录接口
@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = get_user(form_data.username)
    if not user or not verify_password(form_data.password, user["hashed_password"]):
        raise HTTPException(status_code=401, detail="用户名或密码错误")

    access_token = create_access_token(data={
        "sub": user["username"],
        "role": user["role"]
    })
    return {"access_token": access_token, "token_type""bearer"}

3. 获取当前用户及权限依赖(dependencies.py)

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

defget_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        role: str = payload.get("role")
        if username isNoneor role isNone:
            raise HTTPException(status_code=401, detail="无效的 token")
        return {"username": username, "role": role}
    except JWTError:
        raise HTTPException(status_code=401, detail="验证 token 失败")

# 权限依赖:仅允许管理员访问
defrequire_admin(current_user: dict = Depends(get_current_user)):
    if current_user["role"] != "admin":
        raise HTTPException(status_code=403, detail="权限不足,仅管理员可访问")
    return current_user

4. 使用依赖项控制接口访问权限(main.py)

from fastapi import FastAPI, Depends
from dependencies import get_current_user, require_admin

app = FastAPI()

@app.get("/user/profile")
def read_profile(current_user: dict = Depends(get_current_user)):
    return {"message""欢迎你""user": current_user}

@app.get("/admin/dashboard")
def admin_dashboard(current_user: dict = Depends(require_admin)):
    return {"message""欢迎管理员""user": current_user}

测试说明

  1. 1. 普通用户登录后访问 /user/profile 没问题;
  2. 2. 但如果尝试访问 /admin/dashboard,将收到 403 权限不足错误;
  3. 3. 管理员登录后即可访问两个接口。

你可以用 curl 或 Postman 测试:

# 登录获取 token
curl -X POST http://localhost:8000/token -d "username=alice&password=xxx" -H "Content-Type: application/x-www-form-urlencoded"

# 访问用户信息
curl -H "Authorization: Bearer <token>" http://localhost:8000/user/profile

# 访问管理员面板
curl -H "Authorization: Bearer <token>" http://localhost:8000/admin/dashboard

进阶建议

  • • 可以使用 Enum 类型定义角色;
  • • 将权限控制封装为更通用的函数,例如 require_role("admin")
  • • 支持多角色(如 editor、viewer);
  • • 与数据库配合动态管理权限;
  • • 引入 Casbin 等权限框架进行细粒度控制。

小结

通过依赖项机制,FastAPI 能够非常优雅地实现权限控制。你可以根据当前用户的角色或身份灵活决定是否允许访问接口。相比硬编码判断,依赖注入的方式更具扩展性和复用性,是构建中大型 API 项目的推荐做法。

 

 

 

 

 

 

 

 

【声明】内容源于网络
0
0
人人都懂物联网
专注于分享 AIoT 物联网、嵌入式、Web、AI 技术教程、行业资讯,主站 getiot.tech
内容 390
粉丝 0
人人都懂物联网 专注于分享 AIoT 物联网、嵌入式、Web、AI 技术教程、行业资讯,主站 getiot.tech
总阅读72
粉丝0
内容390