0%

FastAPI自学教程(58) - OAuth2 Scopes安全机制

1.基础用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from fastapi import FastAPI, Security
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(
tokenUrl="token",
scopes={"me": "读取用户信息", "items": "操作项目数据"} # 声明支持的scopes
)

@app.get("/users/me/", response_model=User)
async def read_users_me(
current_user: User = Security(get_current_user, scopes=["me"])
):
return current_user
  • 使用OAuth2PasswordBearer声明OAuth2安全方案,通过scopes参数定义权限范围
  • 通过Security替代Depends声明路径操作依赖项,添加scopes参数指定所需权限
  • 请求处理流程:
    graph TD
      A[客户端请求] --> B{Token是否有效?}
      B -->|无效| C[返回401错误]
      B -->|有效| D{Scope是否匹配?}
      D -->|不匹配| E[返回403权限不足]
      D -->|匹配| F[执行业务逻辑]

2.Scopes校验机制

2.1 Token生成

1
2
3
4
5
6
# 登录时生成包含scopes的token
def create_access_token(data: dict):
to_encode = data.copy()
# 添加scopes字段
to_encode.update({"scopes": ["me"]})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
  • 在JWT token的payload中加入scopes字段存储权限列表
  • 可通过用户实际权限或前端请求动态赋值scopes

2.2 权限校验

1
2
3
4
5
6
7
8
async def get_current_user(security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme)):
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
token_scopes = payload.get("scopes", [])

# 校验请求所需的所有scopes
for scope in security_scopes.scopes:
if scope not in token_scopes:
raise HTTPException(403, "权限不足")
  • 通过SecurityScopes对象获取当前路径操作所需的所有scopes
  • scopes属性包含所有依赖项链声明的权限集合

3.依赖项层次结构

1
2
3
4
5
6
7
8
9
10
11
12
async def get_current_active_user(
current_user: User = Security(get_current_user, scopes=["me"])
):
if current_user.disabled:
raise HTTPException(400, "用户未激活")
return current_user

@app.get("/users/me/items/")
async def read_own_items(
current_user: User = Security(get_current_active_user, scopes=["items"])
):
return [{"item_id": "Foo", "owner": current_user.username}]
  • 依赖项树中的scopes会合并传递,例如:
    • /users/me/items/最终校验["me", "items"]两个scopes
    • /users/me/仅校验["me"]
  • 每个Security依赖项可声明自己的scopes需求

4.生产环境建议

  1. Scope命名规范

    • 使用service:action格式(如users:read
    • Google风格URL命名(如https://api.example.com/auth/drive
  2. 安全增强

    • 登录时过滤无效scopes请求,只返回用户真实拥有的权限
    • 结合HTTPS传输敏感scope信息
  3. 文档集成

    • 在Swagger UI中展示可选的scopes列表
    • 通过responses参数补充错误状态码说明

测试命令示例:

1
2
# 获取带scope的token
curl -X POST "http://localhost:8000/token" -d "username=foo&password=secret&scopes=me items"