news 2026/3/24 6:06:16

手机扫码登录详细设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手机扫码登录详细设计

手机扫码登录(Web/PC 扫码)详细设计

目标:用户在Web/PC 端看到二维码,用手机 App扫码确认后,Web/PC 端自动登录。
关键词:一次性二维码、短时会话、状态机、WebSocket/轮询、JWT/Session、风控与安全。


1. 场景与需求

1.1 核心场景

  1. Web/PC 打开登录页 → 展示二维码
  2. 手机 App 扫码 → 告知“是否在某某设备登录?”
  3. 用户在手机确认/取消 → Web/PC 实时得到结果并完成登录

1.2 业务需求

  • 低延迟:扫码后 1s 内让 Web/PC 感知状态变化(理想)
  • 高可用:登录链路要抗抖动(网络波动、页面刷新、重复扫码)
  • 安全:防伪造二维码、防重放、防钓鱼、防越权
  • 可观测:全链路埋点、日志、指标、告警
  • 可扩展:支持多端(H5/PC/小程序)、支持二次确认、支持风控

1.3 非功能指标建议

  • 二维码有效期:60–120s
  • 单二维码最多允许:N 次状态查询(防刷,如 60 次/分钟)
  • 扫码确认超时:60s
  • 登录态:
    • Web 端:HttpOnly Cookie Session 或 JWT Cookie(同站策略)
    • App 端:已有登录态(AccessToken + RefreshToken)

2. 总体架构

2.1 角色

  • Web/PC:展示二维码、监听状态变化、拿到登录态
  • App:扫码、拉取二维码信息、展示确认页、提交确认/取消
  • Auth 服务:生成二维码、维护状态机、签发 Web 登录态
  • Redis:保存二维码会话(短期)、状态、一次性票据
  • 消息通道:WebSocket(优先)或长轮询/短轮询(兜底)
  • 风控/安全:设备指纹、IP 风险、地理位置异常、黑名单等(可选)

2.2 数据与通道选择

  • 状态存储:Redis(TTL 强制过期)
  • 状态通知
    • 首选:WebSocket(服务端推送)
    • 兜底:长轮询(30s)或短轮询(1–2s)
  • Web 登录态颁发
    • 方案 A(推荐):一次性 ticket 交换 cookie/session
    • 方案 B:扫码确认后直接写入 Web session(需要能定位到 Web 连接)

3. 核心状态机设计

3.1 状态定义

  • DISPLAYED:二维码已生成(Web 已拿到并展示)
  • SCANNED:手机已扫码(已识别二维码)
  • CONFIRMED:用户在手机确认
  • CANCELLED:用户在手机取消
  • EXPIRED:二维码过期
  • CONSUMED:Web 已完成登录(票据已使用)

3.2 状态转换(严格)

DISPLAYED -> SCANNED -> CONFIRMED -> CONSUMED DISPLAYED -> SCANNED -> CANCELLED DISPLAYED -> EXPIRED SCANNED -> EXPIRED CONFIRMED -> EXPIRED (若 Web 长时间不换票据,ticket 可单独更短 TTL)

3.3 幂等与并发

  • 扫码可能重复:SCANNED状态写入应幂等(SETNX 或 Lua)
  • 确认可能重复提交:确认接口应幂等(状态已 CONFIRMED 则返回成功)
  • Web 页面刷新:同一个qrId允许重新订阅状态(WebSocket 重新连/轮询继续)

4. 二维码内容设计(非常关键)

4.1 二维码里放什么?

不要直接放 userId / token。
只放一个随机、不可预测的会话标识:

  • qrId:128-bit 随机数(Base64URL / Hex)
  • 可选:sig:服务端签名(防伪造二维码)
  • 可选:ts:生成时间戳(辅助校验)

示例(URL Scheme):

myapp://qr-login?qrId=AbCd...&ts=173...&sig=...

或(HTTPS Deep Link / Universal Link):

https://auth.example.com/qr/scan?qrId=...&ts=...&sig=...

4.2 防伪造(建议做)

  • sig = HMAC-SHA256(secret, qrId + "." + ts)
  • 服务端校验:abs(now - ts) <= 120sHMAC一致

5. Redis Key 设计

5.1 Key 结构(示例)

  • qr:login:{qrId}→ Hash

    • status:DISPLAYED / SCANNED / CONFIRMED / CANCELLED
    • createdAt
    • expireAt
    • webClientId(可选:WebSocket 连接标识)
    • deviceHint(可选:扫码设备信息,用于 Web 展示提示)
    • confirmedUserId(CONFIRMED 后写入)
    • ticket(CONFIRMED 后写入一次性票据)
  • TTL:120s(二维码本体)

  • qr:ticket:{ticket}→ String(userId 或会话信息)

    • TTL:30s(短!一次性!)

5.2 原子更新建议

用 Lua 做状态推进,确保:

  • 不允许从 CANCELLED 再 CONFIRMED
  • 不允许过期后再 CONFIRMED
  • CONFIRMED 只生成一次 ticket

6. 交互流程

6.1 Web/PC 端流程

  1. GET /api/qr-login/init→ 返回qrId、二维码图片/URL、过期时间
  2. Web 建立订阅:
    • WebSocket:ws://.../ws/qr-login?qrId=...
    • 或轮询:GET /api/qr-login/poll?qrId=...
  3. 收到状态:
    • SCANNED:UI 提示“已扫码,请在手机确认”
    • CONFIRMED:拿到ticket,调用POST /api/qr-login/exchange换取登录态
    • CANCELLED/EXPIRED:提示并刷新二维码

6.2 App 端流程

  1. 扫码解析qrId/ts/sig
  2. 调用POST /api/qr-login/scan(App 已登录,带 App Token)
  3. 服务端返回 Web 端信息(设备、地点、浏览器)用于确认页展示
  4. 用户点击确认:
    • POST /api/qr-login/confirm
  5. 或取消:
    • POST /api/qr-login/cancel

7. API 设计(REST 示例)

7.1 生成二维码

GET/api/qr-login/init

响应:

{"qrId":"AbCdEf...","qrUrl":"myapp://qr-login?qrId=...&ts=...&sig=...","expireInSeconds":120}

7.2 Web 轮询状态(兜底)

GET/api/qr-login/poll?qrId=...&sinceVersion=...

响应:

{"status":"SCANNED","deviceHint":"iPhone 15 · 上海","ticket":null,"expireInSeconds":80}

7.3 App 扫码上报

POST/api/qr-login/scan

{"qrId":"...","ts":1730000000,"sig":"..."}

返回(给 App 确认页展示):

{"status":"SCANNED","webInfo":{"ipCity":"New York","browser":"Chrome","os":"Windows","time":"2026-01-31T12:00:00Z"}}

7.4 App 确认登录

POST/api/qr-login/confirm

{"qrId":"..."}

7.5 App 取消

POST/api/qr-login/cancel

{"qrId":"..."}

7.6 Web 换票据拿登录态

POST/api/qr-login/exchange

{"qrId":"...","ticket":"TICKET_..."}

响应:Set-Cookie(Session/JWT Cookie) +{ "ok": true }


8. WebSocket 推送设计(推荐)

8.1 建连

GET ws://auth.example.com/ws/qr-login?qrId=...

服务端验证:

  • qrId存在且未过期
  • 绑定连接connIdqr:login:{qrId}.webClientId

8.2 推送消息

{"qrId":"...","status":"SCANNED","deviceHint":"..."}

CONFIRMED推送可带ticket(建议只带 ticket,不带 userId):

{"qrId":"...","status":"CONFIRMED","ticket":"TICKET_..."}

8.3 多实例

  • Redis Pub/Sub 或 MQ 广播状态变更
  • 各节点维护本地qrId -> wsSession映射,收到事件后推送

9. 安全设计清单

  • ticket一次性GETDEL或 Lua 原子删除
  • sig+ts防伪造二维码
  • Web 端 Cookie:HttpOnly + Secure + SameSite
  • exchange校验Origin/Referer
  • 限流:init/poll/scan/confirm 分别按 IP/userId 维度
  • App 确认页展示 Web 端信息(地点/浏览器/时间),让用户识别异常
  • 风控扩展:异地登录/代理/VPN/黑名单/二次验证

10. 可观测性

关键指标:

  • init 成功率/耗时
  • 扫码率(init→scan)
  • 确认率(scan→confirm)
  • 换票成功率(confirm→exchange)
  • 过期率、取消率

日志:

  • qrId贯穿全链路(trace tag)
  • userId 脱敏(hash),IP/UA 记录用于风控追踪

11. Java 落地要点(Spring Boot)

关键组件:

  • QrLoginService:状态机推进(Lua)
  • RedisRepository:Key/TTL 封装
  • WebSocketHandler:连接管理与推送
  • AuthTokenService:签发 Web session/JWT
  • RateLimit:限流(网关优先)

Lua(伪代码简化):

-- KEYS[1] = qr:login:{qrId}-- ARGV[1] = targetStatuslocalst=redis.call('HGET',KEYS[1],'status')ifnotstthenreturn{err="NOT_FOUND"}endifst=='CANCELLED'orst=='CONSUMED'orst=='EXPIRED'thenreturn{ok=0,status=st}end-- ...按状态推进(略)return{ok=1}

12. 必测用例清单

  • 正常:init → scan → confirm → exchange
  • cancel:scan → cancel(Web 及时感知)
  • 过期:init 后不扫码,Web 刷新二维码
  • 重复扫码/重复确认/重复 exchange(幂等 + ticket 一次性)
  • Web 刷新/断网重连(仍能继续)
  • 限流触发与恢复
  • 伪造 sig / 篡改 qrId / 过期 ts 全部失败

13. 常见坑

  • 把用户信息/Token 塞进二维码(等于送号)
  • ticket TTL 太长(被截获风险更大)
  • 只做轮询(高并发下把服务打爆)
  • 不做幂等(重复扫码/确认导致状态乱)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/15 14:59:56

汽车制造企业使用Web编辑器导入Excel参数表时,如何生成动态图表?

企业网站后台管理系统富文本编辑器功能扩展开发记录 一、需求分析与技术选型 作为北京某软件公司的前端开发工程师&#xff0c;近期接到客户需求&#xff1a;在企业网站后台管理系统的文章发布模块中增加Word粘贴、Word文档导入以及微信公众号内容粘贴功能。经过详细分析&…

作者头像 李华
网站建设 2026/3/24 1:44:23

导师严选10个AI论文写作软件,研究生高效写作必备!

导师严选10个AI论文写作软件&#xff0c;研究生高效写作必备&#xff01; AI 工具如何助力论文写作&#xff1f;高效与精准的双重保障 在研究生阶段&#xff0c;论文写作是每位学生必须面对的重要任务。随着人工智能技术的不断进步&#xff0c;越来越多的 AI 工具被引入到学术…

作者头像 李华
网站建设 2026/3/18 11:06:50

stm32f407 SD卡升级 bootloader程序 基于sdio fatfs系统的stm32

stm32f407 SD卡升级 bootloader程序 基于sdio fatfs系统的stm32 bootloader程序 功能简介&#xff1a; 本程序使用fatfs系统读取bin文件。 开机后会自动检测sd卡&#xff0c;检测到sd卡后&#xff0c;再读取固定名称的bin文件&#xff0c;之后会对bin文件进行首包校验&#xf…

作者头像 李华
网站建设 2026/3/13 22:40:55

蛋白质测序常见问题汇总(一)

蛋白质测序常见问题汇总&#xff08;一&#xff09;蛋白质研究常常涉及到蛋白质鉴定以及对蛋白质的序列研究&#xff0c;而刚接触蛋白测序方面的新手往往会遇到各种各样的问题&#xff0c;在这期小编给大家贴心汇总了有关蛋白质测序大家比较关心的一些问题&#xff0c;希望对大…

作者头像 李华
网站建设 2026/3/15 3:50:01

金融风控系统通过Web编辑器导入Word报告时,如何保留修订痕迹?

广东某国企项目负责人技术选型与开发实施记录 一、需求背景与核心目标 为满足政府客户在企业网站后台管理系统升级需求&#xff0c;需在UEditor富文本编辑器中扩展三大功能&#xff1a; Word粘贴增强&#xff1a;支持图文混排、样式保留、图片自动上传至华为云OBSOffice文档…

作者头像 李华