Commit Graph

2 Commits

Author SHA1 Message Date
costcodev 44f46a0e40 feat(BIZ-129): Flask-Limiter 集成 + 登录/重置限流
- requirements.txt: flask-limiter>=4.0
- app.py: 创建 Limiter 实例(memory:// 存储,60/分钟默认)
- auth_api.py:
  - 简化 register_auth_api(app, limiter=None)——limiter 仅作能力标记
  - _rate_limit(rate, methods) 装饰器:手写 IP+endpoint 滚动窗口限流
    (Flask-Limiter 在测试 client 下不生效,故手动实现;多进程需切换 Redis)
  - login / reset-request / reset-confirm 三个路由应用装饰器

限流策略(架构决策 #5/#6 配合):
  - /login: 5 次/分钟(IP 级爆破防御,配合账号级 5 次锁定 15min)
  - /reset-request: 3 次/分钟(防邮件/短信滥用)
  - /reset-confirm: 5 次/分钟(防 token 暴力猜解)

测试结果(test_client 压测):
  - login: 1-5 次业务 401,6 次起 429 ✅
  - reset-request: 1-3 次业务 200,4 次起 429 ✅

依赖:commit b002e92 的 7 路由蓝图。

BIZ-127 架构决策:
  ✓ #5 限流 5 次/分钟(IP 级,与账号级锁定 15min 双重防御)

Co-authored-by: multica-agent <github@multica.ai>
2026-09-05 07:13:50 +08:00
costcodev b002e929dc feat(BIZ-129): auth_api 蓝图 + 7 接口(login/logout/me/refresh/change-password/reset-request/reset-confirm)
- auth_api.py: Blueprint 独立文件,不污染 app.py 业务路由
- session 存 sha256 hash 入库(架构决策 #2,依赖 auth.py lookup_session)
- cookie HttpOnly + SameSite=Lax(Secure 留给部署层 nginx)
- 错误返回统一:{'success': False, 'error': str, 'code': str}
- 防用户名枚举:reset-request 即便用户不存在也返回 ok
- change-password 成功后强制吊销当前 session(防 session 复用)
- reset-confirm 成功后吊销该用户所有 session(防攻击者已登录状态)

依赖:auth.py + auth_db.py(commit ab9b62e)

BIZ-127 架构决策对齐:
  ✓ #1 bcrypt rounds=12(依赖 auth.py hash_password)
  ✓ #2 session token_hash = sha256(cookie_value)
  ✓ #5 5 次失败锁定 15 分钟(依赖 auth.py authenticate)
  ✓ #6 重置 token token_urlsafe(32) + 2h 过期 + 一次性(依赖 auth.py create_reset_token / consume_reset_token)
  ✓ #8 操作日志 90 天保留(依赖 auth.py write_op_log)

未完成(commit 2/3/4):
  - Flask-Limiter 集成(commit 2)
  - 前端 3 页(commit 3)
  - pytest 端到端(commit 4)

Co-authored-by: multica-agent <github@multica.ai>
2026-09-05 07:09:08 +08:00