两步验证(Passport 令牌)
Passport 支持基于 TOTP(RFC 6238)的登录两步验证。已绑定「Passport 令牌」的账号在网页端登录时,密码校验通过后需再完成一次第二因子验证,可选邮箱验证码或 Passport 令牌动态码(二选一,用户自选)。
特殊场景(注册账号、企业激活、忘记密码、扫码登录确认等)不涉及两步验证,行为不变。
Passport 令牌轻应用
令牌的绑定与动态码查看在 mellme App 的「Passport 令牌」轻应用中完成(专业应用分组):
| 项目 | 说明 |
|---|---|
| 入口 | mellme App → 服务 → 专业应用 → Passport 令牌 |
| 地址 | https://mellme.vancone.com/lite-app/passport-2fa-token/ |
| 认证 | mellme 宿主注入的 passport_token Cookie(与其它轻应用一致) |
| 功能 | 一键绑定令牌、查看 30 秒动态码、解绑 |
绑定流程:进入轻应用 → 「一键绑定」→ 完成。绑定在 mellme 登录态下自动完成(服务端把密钥下发给当前会话),无需扫码;绑定后动态码即在本应用内展示,登录时直接照抄即可。解绑需输入当前有效动态码,防止拿到已登录会话的他人直接解绑。
登录流程变化(网页端)
输入账密 → 密码校验通过
├─ 未绑定令牌 → 直接签发 token(与原流程一致)
└─ 已绑定令牌 → 返回 code 10008 + ticket + 可用方式列表
├─ 邮箱验证码:服务端发码 → 输入验证码
└─ Passport 令牌:打开 mellme 查看动态码 → 输入
→ POST /login/2fa/verify 换取正式 token
- ticket 有效期 5 分钟、一次性,过期需重新走密码登录。
- 动态码 6 位、30 秒刷新,允许 ±1 个步长的时钟漂移;每个动态码只能成功消费一次(防重放)。
- 邮箱验证码发送有 60 秒冷却,5 分钟有效,连续输错 5 次锁定。
- 原生客户端(APP / DESKTOP / ANDROID,
passport.totp.skip-client-types)暂不强制两步验证,待客户端提供验证 UI 后收紧。
相关接口
所有接口路径前缀为 /api/passport/service/v1,响应为标准 {code, message, data} 包络。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /account/totp | 查询绑定状态;已绑定时返回共享密钥(供轻应用本地计算动态码) |
| POST | /account/totp/binding | 开始绑定:生成密钥与 otpauth URL(需登录) |
| POST | /account/totp | 确认绑定:携带首枚有效动态码(需登录) |
| DELETE | /account/totp | 解绑:携带当前有效动态码(需登录) |
| POST | /login/2fa/email | 为两步验证挑战发送邮箱验证码(body: {ticket}) |
| POST | /login/2fa/verify | 校验第二因子并签发正式 token(body: {ticket, method, code},method 取 EMAIL / TOTP) |
登录错误码:10008 需要两步验证(data 含 ticket 与 methods)、10009 验证码错误、10010 挑战已过期、10011 尝试次数过多。令牌管理错误码:20001 已绑定、20002 未绑定、20003 动态码错误、20004 尝试次数过多。
存储
- 表
t_user_totp(vancone_passport库,DDL 见 passport 仓库docs/sql/user_totp.sql):每账号一条记录,软删除。 - 动态码挑战、防重放与错误计数存 Redis(key 前缀
login:2fa:*、totp:*)。