- 新增 RedisSystemOperationPasswordKey 常量函数(pkg/constants/redis.go) - 新增 operation_password Service(Set/IsSet/Verify,bcrypt 哈希存 Redis) - 新增 SuperAdminHandler 及两个接口: - POST /api/admin/super-admin/operation-password(设置/重置,仅超级管理员) - GET /api/admin/super-admin/operation-password/status(查询是否已设置) - AgentRecharge.OfflinePay 操作密码验证从"查当前用户登录密码"改为"全局操作密码 Verify" - Bootstrap/路由/文档生成器同步注册
3.9 KiB
Context
当前代理充值线下确认接口(OfflinePay)通过将 operation_password 与操作人自己的登录密码(account.Password)做 bcrypt 对比来实现操作密码验证。这个机制存在两个问题:
- 缺乏独立性:操作密码与登录密码耦合,修改登录密码即等于修改操作密码,无法独立管控。
- 安全边界不清:需要操作密码的敏感操作(如确认大额资金流转)应由超级管理员统一管控,而非各操作人分散管理。
设计决策:操作密码存 Redis,不开新表。原因:操作密码是全局单一配置,没有历史版本需求,Redis 的 SET/GET 完全满足需求,避免引入新表的维护成本。
Goals / Non-Goals
Goals:
- 超级管理员可以设置/修改全局操作密码(存 Redis,bcrypt 哈希)
- 提供查询接口返回操作密码是否已设置(不暴露密码本身)
OfflinePay的操作密码验证从"当前用户登录密码"改为"全局操作密码"- 封装
VerifyOperationPassword工具函数,供后续接口统一复用
Non-Goals:
- 不做操作密码的过期机制(非当前需求)
- 不做操作密码历史记录
- 不修改除
agent_recharge.OfflinePay以外的其他接口(其他接口暂无此需求)
Decisions
决策1:存储介质选 Redis 而非数据库新表
选择:Redis SET system:operation_password <bcrypt_hash> 永久存储(无 TTL)。
理由:全局单一配置,无历史记录需求,Redis 的简单 KV 足够。Key 命名遵循项目规范,定义在 pkg/constants/redis.go。
备选:新建 tb_system_config 表 → 引入表管理、迁移、GORM 操作,过度设计。
决策2:新接口归属路径
选择:POST /api/admin/super-admin/operation-password(设置/修改)和 GET /api/admin/super-admin/operation-password/status(查询状态)。
理由:/super-admin/ 路径前缀清晰表达"仅超级管理员"语义,与现有路由命名惯例一致。Handler 层检查 userType == UserTypeSuperAdmin,非超级管理员返回 403。
决策3:Service 层封装独立的 OperationPassword 服务
选择:新建 internal/service/operation_password/service.go,提供 Set(ctx, password) 和 Verify(ctx, inputPassword) error 两个方法。
理由:将操作密码逻辑从 agent_recharge Service 中解耦,后续接口可直接注入复用,避免逻辑散落多处。
决策4:未设置时的行为
选择:操作密码未设置时,Verify 返回"操作密码未设置,请联系超级管理员"错误,拒绝操作。
理由:不降级为登录密码(安全边界清晰)。初次上线前超级管理员需先设置操作密码。
决策5:bcrypt 哈希存 Redis
选择:Set 时用 bcrypt.GenerateFromPassword 哈希后存储,Verify 时用 bcrypt.CompareHashAndPassword 对比。
理由:即使 Redis 被访问,也无法还原明文密码。与现有登录密码处理方式一致。
Risks / Trade-offs
[风险] 初次上线前操作密码未设置
→ OfflinePay 接口会返回"操作密码未设置"错误。需在上线前由超级管理员设置初始操作密码。
[风险] Redis 数据丢失 → 如 Redis 数据被清空,操作密码丢失,所有需要操作密码的接口将拒绝服务。 → 缓解:Redis 持久化(AOF/RDB)已在生产环境启用;超级管理员可随时重设。
[风险] bcrypt 计算开销 → bcrypt 默认 cost=10,约 100ms/次。此接口调用频率极低(管理操作),不影响系统整体性能。
Migration Plan
- 部署代码变更(新接口 + Redis 验证逻辑)
- 超级管理员登录后台,调用
POST /api/admin/super-admin/operation-password设置初始操作密码 - 验证
GET /api/admin/super-admin/operation-password/status返回已设置 - 验证
OfflinePay接口使用新操作密码可正常通过