# 统一认证依赖注入 **日期**: 2026-01-29 **类型**: 架构优化 **影响范围**: 认证系统、API 路由 ## 背景 项目中存在两个依赖注入文件,导致职责不清: 1. **`app/api/deps.py`** - API 层依赖注入 2. **`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` 导入业务相关的依赖: ```python 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` ## 技术细节 ### 认证依赖注入实现 ```python # 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() ``` ### 使用示例 ```python # 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. 导入检查 ```bash # 确认所有 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. 功能测试 ```bash # 运行集成测试 docker exec jointo-server-app pytest tests/integration/ -v ``` 所有认证相关的测试应该通过。 ### 3. API 测试 使用 Postman 或 curl 测试需要认证的端点: ```bash # 获取 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 " ``` ## 架构优势 1. **职责清晰**: `app/core/` 专注基础设施,`app/api/` 专注业务逻辑 2. **易于维护**: 业务相关的依赖集中在 `app/api/deps.py` 3. **符合分层架构**: 核心层不依赖业务层 4. **便于扩展**: 未来添加新的 API 依赖时,直接在 `app/api/deps.py` 中添加 ## 相关文档 - [系统设计](../../requirements/backend/03-system-design.md) - [用户服务文档](../../requirements/backend/04-services/user/user-service.md) - [API 设计规范](../../requirements/api-design-specification.md)