扫码登录的设计与实现

https://www.bilibili.com/video/BV1nJY7efEfz/?spm_id_from=333.337.search-card.all.click\&vd_source=12d5954938d20d50645e227a6a728c76

扫码登录 = 用手机作为可信设备,帮 PC 完成一次"无密码登录授权"

核心是三点:

  1. 一个临时二维码(带状态)
  2. 手机端确认身份
  3. PC 端被动等结果(长轮询 / WebSocket)

二、扫码登录里涉及哪些角色?

一共 4 个角色,别少想了:

复制代码
[PC 浏览器]
[PC Web Server]
[Mobile App]
[统一认证服务 Auth Server]

真实大厂一定有 统一认证服务,不是各业务自己玩。


三、完整流程(一步一步,重点)

下面是最标准、最通用的一套流程(微信 / 钉钉 / 飞书 / GitHub 都是变种)。


Step 1:PC 请求"登录二维码"

PC → Web Server

复制代码
GET /login/qrcode

Web Server → Auth Server

Auth 服务生成一个 临时登录凭证

text 复制代码
qrId = UUID

并初始化状态:

json 复制代码
{
  "qrId": "abc123",
  "status": "WAIT_SCAN",
  "expireTime": now + 2min
}

👉 注意:此时还没登录


PC 拿到二维码

二维码内容不是账号,而是:

复制代码
https://auth.xxx.com/scan?qrId=abc123

Step 2:PC 开始"等结果"

PC 页面此时会:

  • 开一个 WebSocket
  • 或者 轮询接口
text 复制代码
GET /login/qrcode/status?qrId=abc123

Step 3:手机扫码

手机扫码 → 打开 App

App 拿到:

复制代码
qrId = abc123

手机 → Auth Server

复制代码
POST /scan
{
  qrId: "abc123",
  userToken: "mobile_login_token"
}

Auth Server 做三件事:

  1. 校验 qrId 是否存在 / 未过期
  2. 校验手机用户已登录
  3. 绑定关系:
json 复制代码
{
  "qrId": "abc123",
  "userId": 10086,
  "status": "SCANNED"
}

👉 此时 PC 仍然未登录


Step 4:手机"确认登录"

App 弹窗:

"是否确认在 PC 登录?"

用户点 确认


手机 → Auth Server

复制代码
POST /confirm
{
  qrId: "abc123"
}

Auth Server:

json 复制代码
{
  "qrId": "abc123",
  "userId": 10086,
  "status": "CONFIRMED"
}

并生成:

  • 登录态(session / jwt)
  • 或一次性登录 ticket

Step 5:PC 被动感知"登录成功"

PC 轮询 / WS 收到:

json 复制代码
{
  "status": "CONFIRMED",
  "loginToken": "xxxxx"
}

PC → Web Server

复制代码
POST /login/byToken

Web Server:

  • 校验 token
  • 写 cookie / session

👉 PC 登录完成


四、状态机是整个系统的核心(重点)

扫码登录 本质是一个状态机

text 复制代码
WAIT_SCAN
   ↓
SCANNED
   ↓
CONFIRMED
   ↓
EXPIRED

每一步都必须是 幂等 + 可校验


五、状态存在哪?Redis 是标配

为什么不用数据库?

  • 生命周期极短(1~2 分钟)
  • QPS 高
  • 不要求持久化

Redis 结构示例

text 复制代码
key: qr:login:abc123
value:
{
  status: SCANNED,
  userId: 10086
}
TTL: 120s

六、PC 端是"怎么等结果的"?

两种主流方式:


方案一:短轮询(简单但不优雅)

text 复制代码
每 1s 调一次状态接口

优点:

  • 实现简单

缺点:

  • 浪费 QPS

方案二:WebSocket / SSE(主流)

复制代码
PC 建立 WS
Auth Server 状态变更 → 主动推送

优点:

  • 实时
  • 低消耗

👉 微信网页版 / 钉钉网页版都是这样。


七、安全点(非常容易被追问)

1️⃣ 二维码必须短期有效

  • 1~2 分钟
  • Redis TTL

2️⃣ 二维码只能用一次

  • CONFIRMED 后立即失效
  • 防止重放

3️⃣ 手机端必须已登录

扫码 ≠ 登录

扫码只是"授权"。


4️⃣ 防止 CSRF / 劫持

  • qrId 不包含任何用户信息
  • token 必须服务端校验

八、为什么这个流程设计得"这么绕"?

你可以用一句话总结:

扫码登录的本质,是把"输入密码"这件事,转移到一个已登录的可信设备上完成

所以复杂点都在:

  • 状态同步
  • 安全校验
  • 跨端通信

九、如果你在面试,我会怎么追问你(提前帮你挡)

面试官:

👉 "为什么不扫码直接登录?"

你答:

因为扫码只是识别设备,登录必须经过用户确认,否则存在被偷拍二维码劫持的风险。


面试官:

👉 "Redis 挂了怎么办?"

你答:

扫码登录是非核心链路,可直接失败,不影响账号安全。


面试官:

👉 "高并发下 Redis 会不会扛不住?"

你答:

key 短期存在、访问模式简单、可水平扩展,QPS 可控。


十、把它压缩成「架构一句话」

扫码登录通过 Redis 维护短期二维码状态,手机端完成身份确认,PC 端通过轮询或 WebSocket 被动感知结果,实现安全的跨端无密码登录。

相关推荐
Miqiuha2 小时前
工作答辩框架
java·开发语言
happymaker06262 小时前
Java学习日记——DAY25(JavaSE完结)
java·开发语言·学习
CHANG_THE_WORLD2 小时前
C++指针与引用:从语法到底层的全面剖析
java·数据结构·c++
HAPPY酷2 小时前
Visual Studio C++ 项目“添加现有项“避坑指南
java·c++·visual studio
追随者永远是胜利者2 小时前
(LeetCode-Hot100)33. 搜索旋转排序数组
java·算法·leetcode·职场和发展·go
计算机毕设vx_bysj68692 小时前
计算机毕业设计必看必学~基于SpringBoot校园招聘系统的设计与实现,原创定制程序、单片机、java、PHP、Python、小程序、文案全套、毕设成品等!
java·spring boot·mysql·课程设计
月明长歌2 小时前
Java 网络编程套接字入门:从“发一段数据”到“写一个可并发的服务器”
java·服务器·网络
没有bug.的程序员2 小时前
Git 高级进阶:分支管理模型内核、Rebase 物理重塑与版本控制协作深度实战指南
java·git·分支管理·版本控制·rebase