TOTP验证码机制 · 双端域名分离 · 全局安全组件 · 可复用设计
| 端 | 域名 | 说明 |
|---|---|---|
| 前台(代理访问) | renyimen.lidamao.online | 实际代理流量入口 |
| 后台(控制面板) | renyimen-panel.lidamao.online | 站点管理/日志查看/配置 |
用户(老板娘)
① 持有 secret(永久凭证,每个子域名独立)
② 使用 Google Authenticator(见到的验证码-app)生成6位TOTP
③ 输入验证码
服务端
① 同时跑相同TOTP算法(基于时间戳,30秒窗口)
② 比对用户输入与服务端计算结果
③ 一致 → 放行;不一致 → 拒绝(不返回任何HTML内容)
| 特性 | 说明 |
|---|---|
| 独立 secret | 每个子域名(renyimen / renyimen-panel)有独立的 secret,互不干扰 |
| 时间同步 | 服务端与客户端使用相同时间窗口(通常30秒) |
| 拒绝即无内容 | 验证码错误时,不返回任何HTML(防探测) |
| 抗暴力破解 | 检测异常输入行为,自动触发冷却 |
触发条件(满足任一即触发):
① 输入速度过快(如 < 500ms 完成一次验证)
② 短时间内连续多次(如 5分钟内 ≥ 3次)验证码错误
冷却机制:
① 首次触发 → 10分钟冷静期,拒绝所有验证请求
② 连续触发2次+ → 站点自动下线(HTTP 503)
③ 站点下线 → 必须手动在服务器上控制恢复上线
④ 恢复后 → 白名单模式,禁止公网访问,仅允许IP手动解封
| 优先级 | 风险 | 方案 |
|---|---|---|
| P0 | 无认证鉴权 | TOTP 验证码(Google Authenticator 方案) |
| P0 | Cookie 明文存储 | AES-256-GCM 加密,密钥从环境变量读取 |
| P0 | 无抗暴力破解 | 输入速度检测 + 错误次数统计 + 10分钟冷却 + 站点下线 |
| P1 | 日志未脱敏 | 入库前过滤 Authorization、Cookie 等敏感头 |
| P1 | 无目标站点白名单 | 白名单模式 + 管理员可临时添加 |
| P1 | 管理界面 XSS | Alpine.js 输出做 HTML 转义(textContent) |
| P1 | Nginx 限流缺失 | limit_req_zone 防止恶意请求 |
| P1 | 无日志自动清理 | TTL 清理任务(保留30天) |
🎯 第二轮评审已启动。 老板娘补充了 TOTP 验证码机制、双端域名分离、抗暴力破解机制,全部 P0+P1 风险须在开发前解决。
inputmode="numeric" + pattern="[0-9]*" → 移动端弹出数字键盘autocomplete="one-time-code" → iOS 12+ 自动读取 Authenticator 粘贴填充response.status 和 response.json() 判断错误类型。| 维度 | 前台 renyimen | 后台 renyimen-panel |
|---|---|---|
| 用户 | AI / 自动化程序 | 老板娘(真人) |
| 风格 | 简洁快进,功能性 | 专业稳重,信息完整 |
| 配色 | 科技青绿 #00d9ff | 中性蓝/紫色系 |
| 交互 | 验证成功即跳转 | 验证成功停留管理面板 |
| 优先级 | 改进项 |
|---|---|
| P0 | 统一 HTTP 401 + JSON 错误体(废弃混淆 body) |
| P0 | 启用 CSP 头 + X-Frame-Options: DENY |
| P1 | autocomplete="one-time-code" iOS 自动填充 |
| P1 | 圆形倒计时环 + 5秒红色警告 |
pyotp 库实现可靠。pyotp.random_base32()(基于 os.urandom(16),密码学安全)| 方案 | 推荐度 | 说明 |
|---|---|---|
| 环境变量 | ❌ 不推荐 | 可被 /proc/ |
| AES-256-GCM 加密文件 | ✅ 推荐 | 主密钥从 KMS/环境变量获取 |
Redis Key 设计:
rate:ip:{ip} → 请求计数
auth:ip:{ip}:failures → 5分钟滑动窗口失败次数 (TTL=300s)
auth:ip:{ip}:cooldown → 冷静期标志 (TTL=600s)
auth:ip:{ip}:strike → 连续触发次数
site:renyimen:offline → 站点下线标志(RDB/AOF 持久化)
| 风险 | 级别 | 方案 |
|---|---|---|
| TOTP Secret 无备份/恢复 | P1 | 纸质备份 + 应急验证码列表 |
| 站点下线无告警 | P1 | Webhook 通知管理员 |
| Redis 持久化未确认 | P1 | 必须开启 RDB/AOF |
前提:① Redis(非SQLite)② Redis 持久化开启 ③ Secret 加密存储 ④ 站点下线联动告警
| 阶段 | 必须实现 |
|---|---|
| MVP | TOTP secret生成+QR码绑定、恢复码、下线状态持久化、后台记住登录(至少7天) |
| 后续 | 前台AI自动化TOTP、集中式secret管理台、多设备登录管理 |
pyotp.verify() 的 ±1 窗口容差意味着同一验证码在 90 秒内可以被使用 3 次!used_code_key = f"totp_used:{request_ip}:{user_input}"
if redis.exists(used_code_key): return False
redis.setex(used_code_key, 90, "1")
| 攻击向量 | 可能性 | 影响力 | 优先级 |
|---|---|---|---|
| Replay Attack(截获重用) | 🟡 中 | 🟡 中 | 高 |
| 暴力破解 DoS(站点下线) | 🟢 低 | 🔴 极高 | 高 |
| Secret 泄露(文件/截图) | 🟡 中 | 🔴 极高 | 高 |
| Root 内存 dump | 🟢 低 | 🔴 极高 | 高 |
必须修复 P0 项后方可上线:Replay 防护 / DoS 下线漏洞 / Secret 加密存储。
| 评审专家 | 结论 | 关键意见 |
|---|---|---|
| 🎨 frontend-reviewer-v2 | ✅ YES | HTTP 401+JSON 替代混淆 body;autocomplete="one-time-code" |
| ⚙️ backend-reviewer-v2 | ✅ 有条件 | Redis(非SQLite);AES-256-GCM加密;Redis持久化 |
| 📋 product-reviewer-v2 | 🔴 NO | 3个阻塞:①AI输入TOTP未定义 ②手机丢失无恢复 ③下线状态未持久化 |
| 🔐 security-reviewer | 🟡 中 | Replay Attack无防护;DoS漏洞;Secret明文存储 |
X-Agent-ID: renyimen),TOTP 只保护后台管理面板。
/etc/renyimen/site_offline)+ Webhook 告警通知老板娘。
| 优先级 | 风险 | 解决方案 |
|---|---|---|
| P0 | TOTP Replay Attack | 一次性验证码标记(Redis Nonce,90秒过期) |
| P0 | 站点下线 DoS 漏洞 | 下线阈值提至连续3次冷静期触发;加 CAPTCHA 解封 |
| P0 | Secret 明文存储 | AES-256-GCM 加密,主密钥从环境变量获取 |
| P0 | 抗暴力破解状态存 SQLite/文件 | 迁移至 Redis + RDB/AOF 持久化 |
| P1 | 手机丢失无恢复机制 | 纸质应急码 + 备用设备绑定 |
| P1 | 站点下线无告警 | Webhook 通知老板娘 |
| P1 | 日志未脱敏 / 无白名单 / XSS / 限流 | 入库过滤 / 白名单模式 / CSP / limit_req_zone |
| P1 | 日志自动清理 | 30 天滚动 TTL |
| 端 | 域名 | 认证方式 | 保护对象 |
|---|---|---|---|
| 前台(代理) | renyimen.lidamao.online | IP 白名单 + Agent 标识头 | AI 代理无障碍访问 |
| 后台(管理) | renyimen-panel.lidamao.online | TOTP 验证码 | 老板娘管理操作 |
| # | 任务 | 前提 |
|---|---|---|
| 1 | 确认"前台 IP 白名单 / 后台 TOTP"分离架构 | 🔴 需老板娘明确 |
| 2 | 明确首次 secret 绑定 + 手机丢失恢复流程 | 🔴 需老板娘明确 |
| 3 | FastAPI 后端骨架 + Redis + P0 安全实现 | ①② 确认后 |
| 4 | Nginx 动态反向代理 + TOTP-Guard 中间件 | 3 完成 |
| 5 | 前端页面(Alpine.js + Tailwind) | 3+4 完成 |
完整评审对话记录已更新至 👉 https://huiyijilu.lidamao.online