Files
shaguabijia-app-server/app/api/deps.py
T
马润林 1aafc28621 feat: 正式 App 后端登录模块 v0.1.0
引入 JWT 认证、极光一键登录、短信 mock 登录与用户表,并补充技术实施文档与部署配置。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 17:37:18 +08:00

59 lines
1.9 KiB
Python

"""API 层共享依赖:DB session、当前登录用户。"""
from __future__ import annotations
import logging
from typing import Annotated
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.orm import Session
from app.core.security import TokenError, decode_token
from app.db.session import get_db
from app.models.user import User
logger = logging.getLogger("shagua.deps")
# auto_error=True → 没传 Authorization header 时直接 403。但我们想 401,
# 所以手动 auto_error=False + raise HTTPException
_bearer = HTTPBearer(auto_error=False, scheme_name="Bearer")
def get_current_user(
credentials: Annotated[HTTPAuthorizationCredentials | None, Depends(_bearer)],
db: Annotated[Session, Depends(get_db)],
) -> User:
"""从 Authorization: Bearer <access_token> 解出当前 user。
失败时统一 401,WWW-Authenticate 头让客户端知道要重新登录。
"""
if credentials is None or credentials.scheme.lower() != "bearer":
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="missing bearer token",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = decode_token(credentials.credentials, expected_type="access")
except TokenError as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=str(e),
headers={"WWW-Authenticate": "Bearer"},
) from e
user_id = int(payload["sub"])
user = db.get(User, user_id)
if user is None or user.status != "active":
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="user not found or disabled",
headers={"WWW-Authenticate": "Bearer"},
)
return user
CurrentUser = Annotated[User, Depends(get_current_user)]
DbSession = Annotated[Session, Depends(get_db)]