Files
SatoNano/docs/architecture.md
2026-01-06 23:49:23 +08:00

9.2 KiB
Raw Permalink Blame History

认证系统架构设计文档

技术栈

组件 技术选型 说明
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 算法(密码哈希竞赛获胜算法):

# 参数配置
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

扩展点

邀请码注册

# 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 登录

# 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

令牌黑名单

# 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"])

配置参考

# .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

测试建议

# 安装测试依赖
uv add --dev pytest pytest-asyncio httpx

# 运行测试
uv run pytest tests/ -v

测试覆盖点:

  • 用户注册(正常、重复用户名、弱密码)
  • 用户登录(正常、错误密码、禁用用户)
  • 令牌刷新(正常、过期令牌、无效令牌)
  • 密码修改(正常、错误当前密码)
  • 权限验证(未认证、已认证、管理员)