FastAPI 全栈后端(四):认证与授权

创作者: Yardon | GitHub: github.com/YardonYan | 版本: v1.0 |



认证 vs 授权:澄清概念

  • 认证 (Authentication):你是谁?------登录凭证(密码、JWT)
  • 授权 (Authorization):你能做什么?------权限检查(管理员 vs 普通用户)

认证像身份证(证明你是谁),授权像工作证(决定你能进哪个房间)。


密码安全存储

python 复制代码
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    return pwd_context.hash(password)

def verify_password(plain: str, hashed: str) -> bool:
    return pwd_context.verify(plain, hashed)

# bcrypt 会自动加盐,一次 hash 的结果每次都不同:
hash1 = hash_password("secret")    # $2b$12$...
hash2 = hash_password("secret")    # $2b$12$...(不同!)
verify_password("secret", hash1)  # True

JWT 原理与实现

JWT(JSON Web Token)把用户信息存在 Token 本身,服务器不需要存:

复制代码
header.payload.signature
python 复制代码
from datetime import datetime, timedelta
from jose import JWTError, jwt

SECRET_KEY = "your-secret-key-change-this"
ALGORITHM = "HS256"

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

def verify_token(token: str) -> dict:
    try:
        return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
    except JWTError:
        raise HTTPException(status_code=401, detail="无效的 Token")

OAuth2 密码模式

python 复制代码
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi import Depends

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")

@app.post("/auth/token")
async def login(form: OAuth2PasswordRequestForm = Depends()):
    user = await authenticate(form.username, form.password)
    if not user:
        raise HTTPException(status_code=401, detail="用户名或密码错误")
    
    access_token = create_access_token({"sub": user.username, "role": user.role})
    return {"access_token": access_token, "token_type": "bearer"}

# 在需要认证的路由中使用
@app.get("/users/me")
async def read_current_user(token: str = Depends(oauth2_scheme)):
    payload = verify_token(token)
    username = payload.get("sub")
    user = await get_user_by_username(username)
    return user

依赖注入实现权限控制

python 复制代码
async def get_current_user(token: str = Depends(oauth2_scheme)):
    payload = verify_token(token)
    username = payload.get("sub")
    user = await get_user_by_username(username)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user

# 可选:检查管理员权限
async def require_admin(user: User = Depends(get_current_user)):
    if user.role != "admin":
        raise HTTPException(status_code=403, detail="需要管理员权限")
    return user

# 路由中使用
@app.delete("/users/{user_id}", dependencies=[Depends(require_admin)])
async def delete_user(user_id: int):
    ...

角色与权限系统

python 复制代码
from enum import Enum

class Role(str, Enum):
    ADMIN = "admin"
    MODERATOR = "moderator"
    USER = "user"

class Permission(str, Enum):
    READ = "read"
    WRITE = "write"
    DELETE = "delete"

ROLE_PERMISSIONS = {
    Role.ADMIN: [Permission.READ, Permission.WRITE, Permission.DELETE],
    Role.MODERATOR: [Permission.READ, Permission.WRITE],
    Role.USER: [Permission.READ],
}

def has_permission(user: User, permission: Permission) -> bool:
    return permission in ROLE_PERMISSIONS[Role(user.role)]

本章小结

认证用 JWT(无状态、可跨域)、依赖注入做权限控制(可组合、可测试)、bcrypt 存密码(安全)。


📌 创作者: Yardon | 🏠 个人网站: GlimmerAI.top

📖 本章是「FastAPI 全栈后端」系列的第 4 章。

🌟 欢迎大家来观看!

相关推荐
huisheng_qaq42 分钟前
【Python基础篇-04】深入理解python的函数、参数与作用域
python·ai·函数·参数作用域
宸津-代码粉碎机5 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
Y3815326625 小时前
SERP API 计费口径:credits_charged、执行失败扣费与退款边界
python·搜索引擎
chenbingjie_c6 小时前
C++ 进阶核心知识点总结:模板、内存分区、new/delete、内存池
开发语言·c++
福兮说7 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea7 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
科技观察哨7 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
落魄大学生之流水线上谋生计7 小时前
Remotion:用 React 写视频,让代码成为剪辑师
react.js
Escalating_xu7 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言
蒸鱼Yuzheng7 小时前
设备端性能工件可靠导出:断点续传、哈希、manifest 与失败恢复
android·自动化测试·python·adb·数据完整性