初次提交
This commit is contained in:
0
backend/app/dependencies/__init__.py
Normal file
0
backend/app/dependencies/__init__.py
Normal file
217
backend/app/dependencies/auth.py
Normal file
217
backend/app/dependencies/auth.py
Normal file
@@ -0,0 +1,217 @@
|
||||
from fastapi import Depends, HTTPException, status, Request
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.security import verify_token
|
||||
from app.services.user_service import UserService
|
||||
from app.schemas.auth import UserResponse
|
||||
from app.models.user import User
|
||||
|
||||
# Bearer token 认证方案
|
||||
security = HTTPBearer()
|
||||
|
||||
async def get_current_user(
|
||||
credentials: HTTPAuthorizationCredentials = Depends(security),
|
||||
db: Session = Depends(get_db)
|
||||
) -> User:
|
||||
"""获取当前认证用户"""
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail={
|
||||
"code": "INVALID_AUTHENTICATION",
|
||||
"message": "无法验证凭据"
|
||||
},
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
try:
|
||||
# 验证令牌
|
||||
payload = verify_token(credentials.credentials, "access")
|
||||
if payload is None:
|
||||
raise credentials_exception
|
||||
|
||||
# 获取用户ID
|
||||
user_id: str = payload.get("sub")
|
||||
if user_id is None:
|
||||
raise credentials_exception
|
||||
|
||||
user_id = int(user_id)
|
||||
|
||||
except (ValueError, TypeError):
|
||||
raise credentials_exception
|
||||
|
||||
# 获取用户信息
|
||||
user_service = UserService(db)
|
||||
user = user_service.get_user_by_id(user_id)
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
|
||||
return user
|
||||
|
||||
async def get_current_user_from_headers(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db)
|
||||
) -> User:
|
||||
"""从请求头中获取当前认证用户(支持userId和token)"""
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail={
|
||||
"code": "INVALID_AUTHENTICATION",
|
||||
"message": "无法验证凭据"
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
# 尝试从多种方式获取token
|
||||
token = None
|
||||
user_id = None
|
||||
|
||||
# 1. 从Authorization header获取
|
||||
authorization = request.headers.get("Authorization")
|
||||
if authorization and authorization.startswith("Bearer "):
|
||||
token = authorization.split(" ")[1]
|
||||
|
||||
# 2. 从token header获取
|
||||
if not token:
|
||||
token = request.headers.get("token")
|
||||
|
||||
# 3. 从userId header获取用户ID
|
||||
user_id_str = request.headers.get("userId")
|
||||
if user_id_str:
|
||||
try:
|
||||
user_id = int(user_id_str)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
# 如果没有token,认证失败
|
||||
if not token:
|
||||
raise credentials_exception
|
||||
|
||||
# 验证令牌
|
||||
payload = verify_token(token, "access")
|
||||
if payload is None:
|
||||
raise credentials_exception
|
||||
|
||||
# 获取token中的用户ID
|
||||
token_user_id: str = payload.get("sub")
|
||||
if token_user_id is None:
|
||||
raise credentials_exception
|
||||
|
||||
token_user_id = int(token_user_id)
|
||||
|
||||
# 如果header中有userId,验证两个ID是否一致
|
||||
if user_id is not None and user_id != token_user_id:
|
||||
raise credentials_exception
|
||||
|
||||
# 使用token中的用户ID
|
||||
final_user_id = token_user_id
|
||||
|
||||
except (ValueError, TypeError):
|
||||
raise credentials_exception
|
||||
|
||||
# 获取用户信息
|
||||
user_service = UserService(db)
|
||||
user = user_service.get_user_by_id(final_user_id)
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
|
||||
return user
|
||||
|
||||
async def get_current_active_user(
|
||||
current_user: User = Depends(get_current_user)
|
||||
) -> User:
|
||||
"""获取当前活跃用户"""
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail={
|
||||
"code": "INACTIVE_USER",
|
||||
"message": "用户账户已被禁用"
|
||||
}
|
||||
)
|
||||
return current_user
|
||||
|
||||
async def get_current_active_user_from_headers(
|
||||
current_user: User = Depends(get_current_user_from_headers)
|
||||
) -> User:
|
||||
"""从请求头获取当前活跃用户"""
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail={
|
||||
"code": "INACTIVE_USER",
|
||||
"message": "用户账户已被禁用"
|
||||
}
|
||||
)
|
||||
return current_user
|
||||
|
||||
async def get_current_verified_user(
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
) -> User:
|
||||
"""获取当前已验证用户"""
|
||||
if not current_user.is_verified:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail={
|
||||
"code": "UNVERIFIED_USER",
|
||||
"message": "用户账户未验证"
|
||||
}
|
||||
)
|
||||
return current_user
|
||||
|
||||
async def get_current_user_response(
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
db: Session = Depends(get_db)
|
||||
) -> UserResponse:
|
||||
"""获取当前用户信息(响应格式)"""
|
||||
user_service = UserService(db)
|
||||
return user_service.to_user_response(current_user)
|
||||
|
||||
async def get_current_user_response_from_headers(
|
||||
current_user: User = Depends(get_current_active_user_from_headers),
|
||||
db: Session = Depends(get_db)
|
||||
) -> UserResponse:
|
||||
"""从请求头获取当前用户信息(响应格式)"""
|
||||
user_service = UserService(db)
|
||||
return user_service.to_user_response(current_user)
|
||||
|
||||
# 可选的认证依赖项(不强制要求认证)
|
||||
async def get_optional_current_user(
|
||||
credentials: HTTPAuthorizationCredentials = Depends(security),
|
||||
db: Session = Depends(get_db)
|
||||
) -> User | None:
|
||||
"""获取可选的当前用户(认证失败时不抛出异常)"""
|
||||
try:
|
||||
return await get_current_user(credentials, db)
|
||||
except HTTPException:
|
||||
return None
|
||||
|
||||
# 权限检查函数
|
||||
def check_user_permission(required_permission: str = None):
|
||||
"""检查用户权限的装饰器工厂"""
|
||||
async def permission_checker(
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
) -> User:
|
||||
# 这里可以根据需要实现更复杂的权限检查逻辑
|
||||
# 目前只检查用户是否活跃
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail={
|
||||
"code": "PERMISSION_DENIED",
|
||||
"message": "权限不足"
|
||||
}
|
||||
)
|
||||
return current_user
|
||||
|
||||
return permission_checker
|
||||
|
||||
# 管理员权限检查(预留)
|
||||
async def get_admin_user(
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
) -> User:
|
||||
"""获取管理员用户(预留功能)"""
|
||||
# 这里可以添加管理员权限检查逻辑
|
||||
# 例如检查用户是否有管理员角色
|
||||
return current_user
|
||||
Reference in New Issue
Block a user