扫码登录接入
扫码登录允许已登录的 VanCone App 用户通过扫描二维码帮助网页完成登录,无需在网页上输入账号密码。本文档描述扫码登录的完整接口契约;常规登录、Token 等其余接口见「公开接口」。
扫码登录涉及两侧调用方:
- Web 端(登录页):创建会话、展示二维码、轮询状态;
- 扫码设备端(VanCone App):解析二维码、上报扫码、确认登录。
会话状态保存在服务端(Redis),有效期 120 秒。
总体流程
Web 浏览器 Passport Service 扫码设备(App)
│ 创建扫码会话 │ │
│─────────────────────────────────>│ 生成一次性 authCode │
│<─── authCode ────────────────────│ │
│ 渲染二维码 │ │
│ 查询状态(每 2s 轮询) │ 上报已扫码 ─────────────│
│─────────────────────────────────>│<─────────────────────────────│
│<─── {status: scanned} ───────────│ 确认登录 ──────────────│
│ │<─────────────────────────────│
│ 查询状态 │ 确认态原子消费,签发 Token │
│─────────────────────────────────>│ + 下发 Cookie │
│<─── {status: confirmed, token} ──│ │
│ 登录完成,跳转回来源页面 │ │
二维码内容约定
二维码内容为自定义协议串:
vancone://login-by-qrcode?auth-code={authCode}
扫码设备解析出 authCode 后,调用下方「上报已扫码」与「确认登录」接口。
接口明细
所有请求与响应均为 JSON,统一前缀 /api/passport/service/v1,响应遵循 Passport 标准结构 {code, message, data}(见「公开接口」的响应格式说明)。
1. 创建扫码会话(Web 调用,免 Token)
POST /api/passport/service/v1/login/qrcode
响应:
{
"code": 0,
"message": "success",
"data": {
"authCode": "8fJ3kQ2p...32位URL安全随机串",
"expiredSeconds": 120
}
}
| 字段 | 说明 |
|---|---|
| authCode | 一次性会话码,由密码学安全随机数生成(32 字符 URL 安全串)。持有它即可完成登录,不要泄露 |
| expiredSeconds | 会话有效期(秒),过期后需重新创建 |
2. 查询扫码状态(Web 调用,免 Token)
GET /api/passport/service/v1/login/qrcode/{authCode}
Web 端以此轮询,建议间隔 2 秒。status 取值:
| status | 说明 |
|---|---|
pending | 已创建,等待扫码 |
scanned | 扫码设备已上报扫码,等待用户在手机上确认 |
confirmed | 确认完成。本响应同时下发 passport_token / passport_username Cookie,data 中附带 token 与 username;且会话被本次轮询原子消费,后续再查询一律返回 expired,Token 不可通过重复轮询二次获取 |
expired | 不存在或已过期 |
{
"code": 0,
"message": "success",
"data": {
"status": "confirmed",
"token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
"username": "admin"
}
}
3. 上报已扫码(扫码设备调用,需要 Token)
POST /api/passport/service/v1/login/qrcode/{authCode}/scan
认证方式与其他接口相同(passport-token 请求头或 passport_token Cookie)。幂等:重复上报返回成功。
4. 确认登录(扫码设备调用,需要 Token)
POST /api/passport/service/v1/login/qrcode/{authCode}/confirm
认证方式同上。幂等:重复确认返回成功(直到会话被 Web 端消费)。允许从 pending 直接确认——设备可将「扫码」与「确认」合并为一步。确认成功后,Web 端的下一次轮询即拿到 confirmed 与 Token。
错误返回
| 场景 | HTTP 状态码 | code | message |
|---|---|---|---|
| 会话不存在或已过期(scan / confirm) | 500 | -1 | qrcode login session not found or expired |
| 会话状态非法流转(如确认已被消费的会话) | 500 | -1 | invalid qrcode login session state |
| scan / confirm 未携带有效 Token | 401 | 11002 | Not authorized |
| 创建会话服务端异常(如 Redis 不可用) | 500 | -1 | 具体错误描述 |
查询状态接口不返回错误码:会话过期体现在
status: expired中,HTTP 状态码仍为 200。
安全要点
authCode一次性有效:确认后被 Web 端轮询取走即从服务端删除,防重放- scan / confirm 必须携带扫码设备自身的有效登录态,未登录设备无法确认
- 会话有效期仅 120 秒,过期必须重新创建,避免长期挂起的待确认会话
- 登录成功会写入登录历史,
loginMethod为QR_CODE(见「公开接口」的登录历史一节)
接入清单
Web 端(登录页):
- 调用「创建扫码会话」,将
authCode按约定格式渲染为二维码 - 每 2 秒调用「查询扫码状态」,展示 pending / scanned / expired
- 轮询到
confirmed即登录完成:服务端已在该响应中下发 Cookie - 会话过期后重新执行第 1 步
扫码设备端(App):
- 扫码解析出
authCode - 调用「上报已扫码」(需要设备自身的有效 Token)
- 用户确认后调用「确认登录」完成登录