You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.4 KiB
6.4 KiB
统一认证依赖注入
日期: 2026-01-29
类型: 架构优化
影响范围: 认证系统、API 路由
背景
项目中存在两个依赖注入文件,导致职责不清:
app/api/deps.py- API 层依赖注入app/core/deps.py- 核心层依赖注入
之前的实现中,两个文件都包含了 get_current_user、get_current_user_optional、get_redis 等业务相关的依赖注入,导致代码重复和职责混乱。
架构原则
根据项目架构设计:
app/core/: 存放全局基础设施,与业务无关的底层能力(如数据库连接、配置管理、日志系统)app/api/deps.py: 存放 API 层的依赖注入,包含业务相关的依赖(如认证、授权、Redis 客户端)
解决方案
1. 明确职责分离
app/api/deps.py - API 层依赖注入(业务相关):
get_current_user- 获取当前登录用户(必需)get_current_user_optional- 获取当前登录用户(可选)get_redis- 获取 Redis 客户端- 其他 API 层需要的依赖注入
app/core/deps.py - 已删除:
- 由于当前没有基础设施相关的依赖注入需求,文件已删除
- 未来如需添加(如全局日志、监控等),可重新创建
2. 统一导入路径
所有 API 路由统一从 app.api.deps 导入业务相关的依赖:
from app.api.deps import get_current_user, get_redis
变更内容
1. 删除 app/core/deps.py
由于所有业务相关的依赖注入已迁移到 app/api/deps.py,app/core/deps.py 文件已无实际用途,因此删除:
- ❌ 删除整个文件
- ✅ 未来如需添加基础设施相关的依赖注入,可重新创建此文件
2. 保留 app/api/deps.py
包含所有 API 层需要的依赖注入:
- ✅
get_current_user- 认证依赖 - ✅
get_current_user_optional- 可选认证依赖 - ✅
get_redis- Redis 客户端依赖 - ✅
security- HTTPBearer 认证方案
3. 更新所有 API 路由导入
将以下文件的导入从 app.core.deps 改为 app.api.deps:
- ✅
server/app/api/v1/users.py - ✅
server/app/api/v1/auth.py - ✅
server/app/api/v1/folders.py - ✅
server/app/api/v1/projects.py - ✅
server/app/api/v1/attachments.py - ✅
server/app/api/v1/credits.py - ✅
server/app/api/v1/recharge.py - ✅
server/app/api/v1/wechat.py - ✅
server/app/api/v1/ai.py - ✅
server/app/api/v1/file_storage.py - ✅
server/tests/integration/test_credit_api.py
技术细节
认证依赖注入实现
# app/api/deps.py
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.database import get_session
from app.services.user_service import UserService
from app.models.user import User
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
session: AsyncSession = Depends(get_session)
) -> User:
"""
获取当前登录用户
从请求头的 Authorization Bearer Token 中解析用户信息
"""
token = credentials.credentials
service = UserService(session)
user = await service.verify_token(token)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无效的认证凭证或 Token 已过期",
headers={"WWW-Authenticate": "Bearer"},
)
return user
async def get_current_user_optional(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(HTTPBearer(auto_error=False)),
session: AsyncSession = Depends(get_session)
) -> Optional[User]:
"""
获取当前登录用户(可选)
如果请求头中没有 Token,返回 None 而不是抛出异常
"""
if not credentials:
return None
token = credentials.credentials
service = UserService(session)
user = await service.verify_token(token)
return user
async def get_redis() -> AsyncGenerator[Redis, None]:
"""获取 Redis 客户端"""
redis = Redis.from_url(
settings.REDIS_URL,
encoding="utf-8",
decode_responses=True
)
try:
yield redis
finally:
await redis.close()
使用示例
# API 路由中使用
from app.api.deps import get_current_user, get_redis
@router.get("/example")
async def example(
current_user: User = Depends(get_current_user),
redis: Redis = Depends(get_redis)
):
# 业务逻辑
pass
影响范围
API 路由
所有需要认证的 API 端点现在统一从 app.api.deps 导入:
- ✅ 用户管理 (
/api/v1/users) - ✅ 认证 (
/api/v1/auth) - ✅ 文件夹 (
/api/v1/folders) - ✅ 项目 (
/api/v1/projects) - ✅ 附件 (
/api/v1/attachments) - ✅ 积分 (
/api/v1/credits) - ✅ 充值 (
/api/v1/recharge) - ✅ 微信 (
/api/v1/wechat) - ✅ AI 服务 (
/api/v1/ai) - ✅ 文件存储 (
/api/v1/file-storage)
测试
- ✅ 更新集成测试导入路径
- ✅ 所有测试通过
验证
1. 导入检查
# 确认所有 API 路由都从 app.api.deps 导入
grep -r "from app.api.deps import" server/app/api/v1/
# 确认 app.core.deps 已删除
ls server/app/core/deps.py 2>/dev/null || echo "✅ 文件已删除"
2. 功能测试
# 运行集成测试
docker exec jointo-server-app pytest tests/integration/ -v
所有认证相关的测试应该通过。
3. API 测试
使用 Postman 或 curl 测试需要认证的端点:
# 获取 Token
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"phone": "13800138000", "code": "123456"}'
# 使用 Token 访问受保护端点
curl -X GET http://localhost:8000/api/v1/users/me \
-H "Authorization: Bearer <token>"
架构优势
- 职责清晰:
app/core/专注基础设施,app/api/专注业务逻辑 - 易于维护: 业务相关的依赖集中在
app/api/deps.py - 符合分层架构: 核心层不依赖业务层
- 便于扩展: 未来添加新的 API 依赖时,直接在
app/api/deps.py中添加