# 认证系统架构设计文档 ## 技术栈 | 组件 | 技术选型 | 说明 | |------|----------|------| | Web 框架 | FastAPI 0.128+ | 异步、高性能、自动 OpenAPI 文档 | | ORM | SQLAlchemy 2.0+ | 异步支持、类型安全 | | 数据库 | SQLite (aiosqlite) | 开发环境,可切换 PostgreSQL | | 密码哈希 | Argon2 | 密码学家推荐的哈希算法 | | 令牌 | PyJWT | JSON Web Token 实现 | | 数据验证 | Pydantic v2 | 高性能数据验证 | | 配置管理 | pydantic-settings | 类型安全的环境变量配置 | ## 项目结构 ``` app/ ├── __init__.py ├── main.py # FastAPI 应用入口 ├── database.py # 数据库连接与会话管理 │ ├── core/ # 核心功能模块 │ ├── config.py # 配置管理 │ ├── security.py # 安全功能(密码哈希、JWT) │ └── exceptions.py # 自定义异常类 │ ├── models/ # SQLAlchemy ORM 模型 │ └── user.py # 用户数据模型 │ ├── schemas/ # Pydantic 数据模式 │ ├── base.py # 基础响应格式 │ ├── user.py # 用户相关 Schema │ └── auth.py # 认证相关 Schema │ ├── repositories/ # 数据访问层 (Repository Pattern) │ ├── base.py # 基础 CRUD 操作 │ └── user.py # 用户数据仓库 │ ├── services/ # 业务逻辑层 (Service Layer) │ ├── user.py # 用户服务 │ └── auth.py # 认证服务 │ └── api/ # API 路由层 ├── deps.py # 依赖注入定义 └── v1/ ├── router.py # 路由聚合 └── endpoints/ ├── auth.py # 认证接口 └── users.py # 用户接口 ``` ## 分层架构 ``` ┌─────────────────────────────────────────────┐ │ API Layer │ │ (FastAPI Endpoints + Deps) │ ├─────────────────────────────────────────────┤ │ Service Layer │ │ (Business Logic + Rules) │ ├─────────────────────────────────────────────┤ │ Repository Layer │ │ (Data Access + Queries) │ ├─────────────────────────────────────────────┤ │ Model Layer │ │ (SQLAlchemy ORM Models) │ ├─────────────────────────────────────────────┤ │ Database │ │ (SQLite / PostgreSQL) │ └─────────────────────────────────────────────┘ ``` ### 各层职责 | 层 | 职责 | 示例 | |----|------|------| | **API Layer** | 处理 HTTP 请求/响应、参数验证、依赖注入 | `auth.py`, `users.py` | | **Service Layer** | 业务逻辑、规则校验、跨仓库协调 | `AuthService`, `UserService` | | **Repository Layer** | 数据库操作封装、查询构建 | `UserRepository` | | **Model Layer** | 数据结构定义、表关系映射 | `User` | ## 数据流 ### 用户注册流程 ``` Client Request │ ▼ ┌─────────────────┐ │ API Endpoint │ POST /api/v1/auth/register │ (auth.py) │ 接收请求、验证 Schema └────────┬────────┘ │ UserCreate ▼ ┌─────────────────┐ │ UserService │ 检查用户名/邮箱唯一性 │ (user.py) │ 哈希密码 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ UserRepository │ 创建用户记录 │ (user.py) │ 提交事务 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Database │ INSERT INTO users └─────────────────┘ ``` ### 用户登录流程 ``` Client Request │ ▼ ┌─────────────────┐ │ API Endpoint │ POST /api/v1/auth/login │ (auth.py) │ 接收凭证 └────────┬────────┘ │ LoginRequest ▼ ┌─────────────────┐ │ AuthService │ 1. 查找用户 │ (auth.py) │ 2. 验证密码 │ │ 3. 检查用户状态 │ │ 4. 更新登录时间 │ │ 5. 生成 JWT └────────┬────────┘ │ ▼ ┌─────────────────┐ │ UserRepository │ 查询用户 │ (user.py) │ 更新 last_login_at └────────┬────────┘ │ ▼ TokenResponse ``` ### 认证流程 (受保护接口) ``` Client Request + Bearer Token │ ▼ ┌─────────────────┐ │ HTTPBearer │ 提取 Authorization header │ (FastAPI) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ get_current_user│ 1. 解码 JWT │ (deps.py) │ 2. 验证签名和过期 │ │ 3. 查询用户 │ │ 4. 检查用户状态 └────────┬────────┘ │ User ▼ ┌─────────────────┐ │ API Endpoint │ 使用已认证用户执行业务逻辑 └─────────────────┘ ``` ## 安全设计 ### 密码存储 使用 **Argon2id** 算法(密码哈希竞赛获胜算法): ```python # 参数配置 time_cost=3 # 迭代次数 memory_cost=65536 # 内存使用 (64MB) parallelism=4 # 并行度 ``` 特性: - 抗 GPU/ASIC 攻击 - 可调参数适应硬件升级 - 自动包含盐值 ### JWT 令牌 **Access Token:** - 算法:HS256 - 有效期:30 分钟(可配置) - 包含:用户 ID、用户名、角色 **Refresh Token:** - 算法:HS256 - 有效期:7 天(可配置) - 仅包含:用户 ID ### 防护措施 | 威胁 | 防护 | |------|------| | 暴力破解 | Argon2 计算成本 | | 时序攻击 | 无论用户是否存在都执行密码验证 | | Token 泄露 | 短期 Access Token + 长期 Refresh Token | | SQL 注入 | SQLAlchemy 参数化查询 | | XSS | JSON 响应(非 HTML) | ## 扩展点 ### 邀请码注册 ```python # schemas/user.py class UserCreate(UserBase): password: str invite_code: str | None = None # 新增字段 # services/user.py async def create_user(self, user_data: UserCreate) -> User: if settings.require_invite_code: await self._validate_invite_code(user_data.invite_code) # ... 原有逻辑 ``` ### OAuth2 登录 ```python # services/oauth.py class OAuthService: async def authenticate_google(self, code: str) -> User: ... async def authenticate_github(self, code: str) -> User: ... # api/v1/endpoints/oauth.py @router.get("/google/callback") async def google_callback(code: str, oauth: OAuthService = Depends()): user = await oauth.authenticate_google(code) tokens = auth_service.create_tokens(user) return tokens ``` ### 令牌黑名单 ```python # models/token_blacklist.py class TokenBlacklist(Base): __tablename__ = "token_blacklist" jti: Mapped[str] = mapped_column(primary_key=True) expires_at: Mapped[datetime] # services/auth.py async def logout(self, token: str) -> None: payload = decode_token(token) await self.blacklist_repo.add(payload["jti"], payload["exp"]) ``` ## 配置参考 ```bash # .env 配置示例 # 环境 ENVIRONMENT=development # development | staging | production DEBUG=true # 安全 SECRET_KEY=your-256-bit-secret-key ACCESS_TOKEN_EXPIRE_MINUTES=30 REFRESH_TOKEN_EXPIRE_DAYS=7 # 数据库 DATABASE_URL=sqlite+aiosqlite:///./satonano.db # PostgreSQL: postgresql+asyncpg://user:pass@localhost/dbname # 密码策略 PASSWORD_MIN_LENGTH=8 PASSWORD_REQUIRE_UPPERCASE=true PASSWORD_REQUIRE_LOWERCASE=true PASSWORD_REQUIRE_DIGIT=true PASSWORD_REQUIRE_SPECIAL=false ``` ## 测试建议 ```bash # 安装测试依赖 uv add --dev pytest pytest-asyncio httpx # 运行测试 uv run pytest tests/ -v ``` 测试覆盖点: - 用户注册(正常、重复用户名、弱密码) - 用户登录(正常、错误密码、禁用用户) - 令牌刷新(正常、过期令牌、无效令牌) - 密码修改(正常、错误当前密码) - 权限验证(未认证、已认证、管理员)