Files
zclaw_openfang/wiki/security.md
iven 5d88d129d1 docs(wiki): Phase B+C完成 — middleware/saas/security/memory 5节模板重构
- middleware.md: 集成契约+3不变量+执行流 (157→136行)
- saas.md: 移除安全重复→引用security.md+Token Pool算法 (231→173行)
- security.md: 吸收saas认证内容成为安全唯一真相源 (158→199行)
- memory.md: 最大压缩363→147行+Hermes洞察提炼+4不变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 21:42:24 +08:00

7.2 KiB
Raw Blame History

title, updated, status, tags
title updated status tags
安全体系 2026-04-22 active
module
security
auth
encryption

安全体系

index 导航。关联模块: saas routing middleware

设计决策

核心原则: 多层防御,深度安全。

决策 为什么
JWT + HttpOnly Cookie 双通道 Tauri 桌面端用 OS keyring 存 JWT浏览器用 HttpOnly Cookie 防 XSS 窃取,双环境统一认证
password_version (pwv) 失效 修改密码后自动使所有已签发 JWT 失效,无需 token 黑名单O(1) 验证
TOTP AES-256-GCM 加密 TOTP 共享密钥不能明文存储,随机 Nonce 防重放,生产环境强制独立密钥
IP 级限流 + 持久化 防暴力破解login 5/min、防刷注册3/hour持久化到 PostgreSQL 避免重启丢失
CORS 白名单强制 生产环境 cors_origins 缺失直接拒绝启动,不允许 * 通配

完整审计报告: docs/features/SECURITY_PENETRATION_TEST_V1.md

关键文件 + 数据流

核心文件

文件 职责
crates/zclaw-saas/src/auth/handlers.rs 认证端点: 登录/注册/刷新/TOTP/密码修改
crates/zclaw-saas/src/auth/totp.rs TOTP 2FA: QR 生成 + 验证 + AES-256-GCM 加密
crates/zclaw-saas/src/middleware.rs HTTP 中间件栈 (10 层): 认证/限流/配额/CORS
crates/zclaw-saas/src/relay/key_pool.rs Token Pool: Key 加密存储 + RPM/TPM 轮换
desktop/src-tauri/src/secure_storage.rs OS Keyring: Win DPAPI / macOS Keychain / Linux Secret
desktop/src-tauri/src/memory/crypto.rs 本地记忆加密: AES-256-GCM (可选)

认证数据流

用户登录 (POST /api/v1/auth/login)
  → Argon2id + OsRng 验证密码
  → 账户锁定检查 (5 次失败 → 15 分钟锁定)
  → 签发 JWT (Claims: user_id, role, pwv)
  → set_auth_cookies():
      zclaw_access_token  (path:/api, 2h TTL, HttpOnly)
      zclaw_refresh_token (path:/api/v1/auth, 7d TTL, HttpOnly)
      Secure: dev=false, prod=true | SameSite=Strict

前端存储:
  → Tauri: OS keyring → saasStore.token
  → 浏览器: HttpOnly Cookie (JS 不可读)
  → localStorage: 仅 saasUrl + account 非敏感信息

集成契约

方向 接口 说明
Provides --> saas auth_middleware, JWT validation, rate limiting 每个 API 请求经过认证层
Provides --> desktop secure_storage, crypto_utils 配置/凭据安全存储
Provides --> admin admin_guard_middleware Admin 路由权限验证

Auth API 接口

公开路由:

方法 路径 说明
POST /api/v1/auth/register 注册 (邮箱 RFC 5322 + 254 字符)
POST /api/v1/auth/login 登录 (5 次/分钟 IP 限流)
POST /api/v1/auth/refresh Token 刷新 (单次使用, 旧 token 撤销)
POST /api/v1/auth/logout 登出

受保护路由:

方法 路径 说明
GET /api/v1/auth/me 当前用户信息
PUT /api/v1/auth/password 修改密码 (触发 pwv 失效)
POST /api/v1/auth/totp/setup TOTP 设置 (生成 QR)
POST /api/v1/auth/totp/verify TOTP 验证激活
POST /api/v1/auth/totp/disable TOTP 禁用 (需密码)

Tauri 安全命令:

命令 说明
secure_store_set OS Keyring 存储
secure_store_get OS Keyring 读取
secure_store_delete OS Keyring 删除
secure_store_is_available Keyring 可用性检测

代码逻辑

JWT Password Version 失效机制

JWT Claims 含 pwv (password_version) 字段
  → auth_middleware 每次验证 JWT 时: Claims.pwv vs DB.pwv
  → 不匹配 → 401 Unauthorized
  → 修改密码 → DB.pwv 递增 → 所有旧 JWT 自动失效
  → 无需 token 黑名单,验证成本 O(1)

密码存储: Argon2id + OsRng

注册/修改密码:
  → OsRng 生成随机盐
  → Argon2id 哈希 (内存硬 + 时间成本)
  → 存储到 users.password_hash
验证:
  → Argon2id::verify(password, stored_hash)
  → 失败计数递增 → 5 次后锁定 15 分钟

TOTP / API Key 加密: AES-256-GCM

TOTP 密钥存储:
  → 随机生成 12 字节 Nonce
  → AES-256-GCM 加密 (密钥: ZCLAW_TOTP_ENCRYPTION_KEY, 64 hex)
  → 存储 nonce + ciphertext
解密:
  → 取出 nonce → AES-256-GCM 解密
  → 解密失败: warn + 跳过 (不阻塞认证)

Provider API Key 同理: heal_provider_keys() 启动时重新加密有效 Key

Token 刷新轮换

POST /api/v1/auth/refresh
  → 验证 refresh_token 有效性
  → 检查旧 token 是否已撤销 (rotation 防重放)
  → 撤销旧 refresh_token (写入 DB revoked_at)
  → 签发新 access_token (2h) + refresh_token (7d)

限流规则

端点 限制 持久化
/api/auth/login 5 次/分钟/IP PostgreSQL
/api/auth/register 3 次/小时/IP PostgreSQL
公共端点 20 次/分钟/IP 内存

SaaS HTTP 中间件栈 (10 层)

# 中间件 路由组 功能
1 public_rate_limit Public IP 限流
2 auth_middleware Protected+Relay JWT/Cookie/API Token 身份验证
3 rate_limit_middleware Protected+Relay 账户级频率限制
4 quota_check_middleware Relay 月度配额检查
5 request_id_middleware All UUID 请求追踪
6 api_version_middleware All API 版本头
7 TimeoutLayer (15s) Protected 非流式请求超时
8 admin_guard Admin 子路由 admin 权限验证
G1 TraceLayer All HTTP 请求追踪
G2 CorsLayer All CORS 白名单

活跃问题 + 陷阱

问题 级别 说明
CSP 已加固 Done Tauri 移除 unsafe-inline scriptconnect-src 限制 http://localhost:* + https://*
TLS 依赖反向代理 长期 Axum 不负责 TLSnginx/caddy 提供 HTTPS 终止
Cookie Secure 开发环境 false 设计意图 开发环境 HTTP 无 Secure生产必须 true

陷阱:

  • JWT 签名密钥: #[cfg(debug_assertions)] 有 fallbackrelease 模式直接 bail 拒绝启动
  • TOTP 加密密钥: 生产必须独立设置 ZCLAW_TOTP_ENCRYPTION_KEY,不从 JWT 密钥派生
  • CORS 白名单: 生产缺失拒绝启动,不允许通配符
  • Refresh Token: 单次使用logout 时撤销到 DBrotation 校验已撤销的旧 token

变更日志

日期 变更 提交
2026-04-21 移除数据脱敏中间件 (稳定化约束) fa5ab4e
2026-04-17 E2E 测试安全链路验证通过
2026-04-16 Agent 隔离修复 + Admin 权限校验
2026-04-13 安全渗透测试 V1: 15 项修复
2026-04-09 CSP 加固 + JWT pwv + 账户锁定 + TOTP 解耦

测试覆盖

功能 测试文件
认证流程 crates/zclaw-saas/tests/auth_test.rs
认证安全边界 crates/zclaw-saas/tests/auth_security_test.rs
账户安全 crates/zclaw-saas/tests/account_security_test.rs
权限矩阵 crates/zclaw-saas/tests/permission_matrix_test.rs
TOTP crates/zclaw-saas/src/auth/totp.rs inline tests
本地加密 desktop/src-tauri/src/memory/crypto.rs inline tests