0Pricing
Python Academy · 课时

依赖注入与身份验证

使用 FastAPI 的 DI 系统实现共享逻辑和基于 JWT 的身份验证。

依赖注入与身份验证 是 CoddyKit 上的免费 Python Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

什么是依赖注入?

FastAPI 的 Depends() 可以声明共享逻辑(数据库会话、身份验证检查和配置),并将其自动注入路由处理函数。

from fastapi import FastAPI, Depends
app = FastAPI()

def get_db():
    db = connect_db()
    try: yield db
    finally: db.close()

@app.get("/users")
def list_users(db = Depends(get_db)):
    return db.query_all("users")

依赖函数

依赖项可以是任何可调用对象。它可以是函数、类,或另一个使用依赖项的函数。

from fastapi import Depends, FastAPI
app = FastAPI()

def common_params(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

@app.get("/items")
def list_items(params: dict = Depends(common_params)):
    return params

@app.get("/users")
def list_users(params: dict = Depends(common_params)):
    return params

类依赖项

使用类作为依赖项可以将相关设置归组。调用该类时,会注入其 __init__ 参数。

from fastapi import Depends, FastAPI, Query
app = FastAPI()

class Pagination:
    def __init__(self, page: int = Query(1,ge=1), size: int = Query(10,ge=1,le=100)):
        self.page = page
        self.size = size
        self.offset = (page - 1) * size

@app.get("/items")
def list_items(pag: Pagination = Depends()):
    return {"offset": pag.offset, "size": pag.size}

OAuth2 密码承载者

使用 OAuth2PasswordBearer 从 Authorization 标头中读取 Bearer 令牌。

from fastapi import FastAPI, Depends
from fastapi.security import OAuth2PasswordBearer
app = FastAPI()

oauth2 = OAuth2PasswordBearer(tokenUrl="/token")

@app.get("/me")
def me(token: str = Depends(oauth2)):
    return {"token": token}   # validate token here

JWT 令牌

使用 python-jose(或 pyjwt)创建并验证 JWT 令牌。登录时返回令牌,并在每个受保护的路由中验证它。

# pip install python-jose passlib
from jose import jwt, JWTError

SECRET_KEY = "change-me"
ALGORITHM = "HS256"

def create_token(data: dict) -> str:
    return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)

def verify_token(token: str) -> dict:
    return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

当前用户依赖项

构建一个 get_current_user 依赖项,用于验证 JWT 并返回经过身份验证的用户。

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

oauth2 = OAuth2PasswordBearer(tokenUrl="/token")

def get_current_user(token: str = Depends(oauth2)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        return payload["sub"]
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

# @app.get("/me")
# def me(user=Depends(get_current_user)): return user

密码哈希

绝不要存储明文密码。使用 passlib 通过 bcrypt 进行哈希处理。

from passlib.context import CryptContext

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

def hash_pw(plain: str) -> str:
    return pwd_ctx.hash(plain)

def verify_pw(plain: str, hashed: str) -> bool:
    return pwd_ctx.verify(plain, hashed)

令牌端点

实现 POST /token,接受表单凭据、验证密码并返回 JWT。

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordRequestForm
app = FastAPI()

@app.post("/token")
def login(form: OAuth2PasswordRequestForm = Depends()):
    user = get_user_by_username(form.username)
    if not user or not verify_pw(form.password, user.hashed_pw):
        raise HTTPException(status_code=401, detail="Bad credentials")
    token = create_token({"sub": form.username})
    return {"access_token": token, "token_type": "bearer"}

API 密钥身份验证

对于较简单的场景,可以从标头或查询参数中验证 API 密钥。

from fastapi import Depends, HTTPException, Security
from fastapi.security import APIKeyHeader

API_KEY_HEADER = APIKeyHeader(name="X-API-Key")

def require_api_key(key: str = Security(API_KEY_HEADER)):
    if key != "secret-key":
        raise HTTPException(status_code=403, detail="Forbidden")
    return key

基于角色的访问控制

在依赖项中添加角色检查,即可在身份验证之上构建权限控制。

from fastapi import Depends, HTTPException

def require_admin(user=Depends(get_current_user)):
    if user.get("role") != "admin":
        raise HTTPException(status_code=403, detail="Admins only")
    return user

# @app.delete("/users/{uid}")
# def delete_user(uid: int, admin=Depends(require_admin)):

依赖缓存

默认情况下,每个请求中只会调用一次依赖项,并且该请求中所有使用它的路由都会共享其结果。

# The same db session object is shared:
@app.get("/summary")
def summary(
    db = Depends(get_db),      # db resolved once
    stats = Depends(get_stats) # get_stats also uses get_db — same db instance
): ...

快速检查

Depends() 在 FastAPI 中有什么作用?

回顾

使用 Depends(func) 注入共享逻辑。使用 OAuth2PasswordBearer、JWT 令牌和 get_current_user 依赖项构建身份验证。使用 passlib/bcrypt 对密码进行哈希处理。将角色检查添加为进一步的依赖项。

常见问题解答

「依赖注入与身份验证」课时是免费的吗?

是的 — 「依赖注入与身份验证」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「依赖注入与身份验证」这节课中我会学到什么?

使用 FastAPI 的 DI 系统实现共享逻辑和基于 JWT 的身份验证。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「依赖注入与身份验证」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. FastAPI 项目设置与第一个端点
  2. 路径参数、查询参数与请求体
  3. 依赖注入与身份验证
  4. 异步端点与数据库集成
← 返回 Python Academy