在这里插入图片描述
我们都熟悉这样的场景:在 PC 上访问一个网站(如微信网页版、淘宝),页面上显示一个二维码。我们拿出手机,打开对应的 App 扫一扫,然后在手机上点击“确认登录”。神奇的事情发生了——PC 上的网页自动刷新,并成功进入了我们的账户。

整个过程无需在 PC 上输入繁琐的账号和密码,体验流畅又安全。

那么,这背后的“魔法”究竟是什么?手机是如何“遥控”PC 完成登录的?本文将带你深入剖析扫码登录的全过程,揭示其背后的技术原理和架构设计。

1. 核心角色与技术选型

要实现扫码登录,我们的“舞台”上需要三位核心“演员”:

  1. PC 端/Web 端: 用户希望登录的目标设备,此时它是一个“未登录”的游客身份。
  2. 手机端 App: 用户已经登录过的、可信的设备,它持有用户的身份凭证。
  3. 服务端: 作为“中央协调人”,负责生成二维码、传递状态、并最终授权 PC 端登录。

核心挑战:跨设备通信
PC 和手机是两个完全独立的设备,它们之间无法直接通信。PC 如何知道用户在手机上“扫码”了,又如何知道用户“确认登录”了呢?解决这个问题的关键,就在于PC 端与服务端之间建立一个“实时”的通信渠道

常见的技术选型有两种:

  • HTTP 长轮询 (Long Polling): PC 端向服务端发起一个请求,如果服务端没有新消息,就“hold”住这个连接不立即返回,直到有新消息(如“已扫码”)或连接超时。PC 端在收到响应或超时后,立刻发起下一个长轮询请求。
  • WebSocket: PC 端与服务端建立一个持久的双向通信通道。服务端可以随时主动向 PC 端推送消息。

为了便于理解,本文将主要以长轮询模型进行讲解,它更易于理解,而 WebSocket 在原理上是相似的,只是实现方式不同。

2. “婚介所”模型:扫码登录的整体流程

我们可以将整个扫码登录过程,比作一个由服务端运营的“婚介所”:

  • PC 端: 来到婚介所的“单身男青年”,希望找到对象(完成登录)。
  • 手机端: “单身男青年”的、可信的“家人”,负责确认身份和同意“婚事”。
  • 二维码: 婚介所为这次“相亲”生成的唯一“配对ID”。
  • 服务端: 婚介所本身,负责撮合、传递信息。

整体流程图 (Sequence Diagram):

注意: 以下为 Mermaid 语法流程图,您可以在支持 Mermaid 的编辑器(如 Typora, VS Code 插件)中将其渲染为可视化图形。

PC/Web 端 服务端 手机端 App 1. 请求登录二维码 2. 生成唯一二维码ID (状态: INITIAL), 存入 Redis 并设过期时间 3. 返回二维码ID 4. 将ID渲染成二维码图片 5. 【长轮询】开始: “二维码ID的状态变了吗?” 6. 用户用手机扫描二维码 7. “我(已登录用户U)扫描了二维码ID” 8. 更新二维码ID状态为 SCANNED 并关联用户信息U (如头像、昵称) 9. 【长轮询】响应: 状态变为 SCANNED, 并返回用户U的头像昵称 10. 页面显示用户头像, 提示“请在手机上确认登录” 11. 【长轮询】再次开始: “二维码ID的状态变了吗?” 12. 用户在手机上点击“确认登录” 13. “用户U确认登录二维码ID” 14. 生成临时授权Token 更新二维码ID状态为 CONFIRMED, 关联Token 15. 【长轮询】响应: 状态变为 CONFIRMED, 并返回临时授权Token 16. 使用临时Token, 请求正式的登录凭证 17. 验证通过, 返回正式凭证(如Session或JWT) PC端登录成功! PC/Web 端 服务端 手机端 App

3. 深度解析:二维码的“一生” (状态机)

从服务端的角度看,每个二维码都有一个清晰的生命周期,可以用一个状态机来描述。这个状态机的管理,非常适合使用 Redis 来实现,因为其高性能的 Key-Value 存储和 TTL (过期时间) 特性。

我们可以为每个二维码 ID,在 Redis 中创建一个 Hash 结构来存储其状态和关联信息。

二维码状态机流程图:

页面加载
手机App扫码
超时未扫码
手机App确认登录
手机App取消登录
超时未确认
PC端凭Token完成登录
流程终止
流程终止
INITIAL
SCANNED
EXPIRED
CONFIRMED
CANCELLED
  • INITIAL (未扫描):

    • 触发: PC 端请求二维码时创建。
    • Redis 存储: HSET qr_id_123 status INITIAL, EXPIRE qr_id_123 60 (设置60秒过期)。
    • PC 端表现: 显示二维码,并开始第一次长轮询。
  • SCANNED (已扫描):

    • 触发: 手机 App 携带自身登录凭证和二维码 ID 请求服务端。
    • Redis 存储: HSET qr_id_123 status SCANNED user_info '{"id":1001, "avatar":"..."}'
    • PC 端表现: 第一次长轮询返回,页面显示用户头像和确认提示,并立即开始第二次长轮询。
  • CONFIRMED (已确认):

    • 触发: 手机 App 发送确认登录的请求。
    • Redis 存储: 服务端生成一个一次性的临时 Token,HSET qr_id_123 status CONFIRMED temp_token 'xyz...'
    • PC 端表现: 第二次长轮询返回,拿到临时 Token,并发起最终的登录请求。
  • EXPIRED / CANCELLED (终态):

    • 二维码在规定时间内未被处理,或用户手动取消,都会进入终态。
    • PC 端的长轮询会收到这些状态,并提示用户“二维码已过期,请刷新”或直接刷新页面。

4. WebSocket vs. 长轮询

对比维度 HTTP 长轮询 (Long Polling) WebSocket
核心原理 客户端拉取 (Client Pull),服务端通过挂起连接来模拟推送 服务端推送 (Server Push),建立持久的双向通道
实时性 准实时,有一定延迟(取决于请求-响应周期) 真·实时,延迟极低
资源消耗 相对较高,每个状态变更都需要一次完整的 HTTP 请求 较低,一次握手后,只需传输少量数据帧
实现复杂度 较低,基于标准 HTTP 相对较高,需要处理连接管理、心跳等
兼容性 极好 良好,但可能受部分老旧网络代理的限制

结论: 长轮询简单可靠,足以应对大多数场景。而对于需要极致实时体验、海量并发连接的大型应用(如企业级聊天工具),WebSocket 是更优的选择。

总结

扫码登录,其本质是一个基于唯一ID(二维码ID),通过一个中央协调者(服务端),来完成跨设备状态同步授信的精妙流程。

  • 二维码是**“一次性桥梁”**,连接了 PC 端和手机端。
  • 手机 App 是**“身份认证官”**,提供可信的登录凭证。
  • PC 端的长轮询/WebSocket 是**“信号接收器”**,时刻等待服务端的指令。
  • 服务端是**“总指挥”**,管理状态机,撮合整个过程。

理解了这个模型,你会发现它不仅能用于登录,还可以扩展到“扫码支付”、“扫码授权第三方应用”等多种多样的场景中,是现代分布式应用设计中一个非常值得学习和借鉴的经典范例。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐