news 2026/5/12 15:56:39

扫码登录背后的黑科技:PC 端与手机端是如何通过 WebSocket 实现“秒级同步”的?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
扫码登录背后的黑科技:PC 端与手机端是如何通过 WebSocket 实现“秒级同步”的?

📱 前言:世界上最遥远的距离

你有没有想过这样一个问题:
当你坐在电脑前打开淘宝,网页上出现一个二维码。
你掏出手机扫了一下,点击“确认登录”。
神奇的事情发生了:电脑网页竟然不需要刷新,瞬间就跳进了首页!

手机和电脑,明明是两个毫无关联的设备,它们不在同一个局域网,甚至可能相隔千里。手机是怎么“告诉”电脑:“喂,我准许你登录了”?

很多人会说:“轮询呗,网页每秒问一次服务器。”
错!这种做法既浪费流量又延迟高。
今天,我们就来揭秘大厂通用的WebSocket 长连接方案,看看这套“隔空传音”的黑科技是如何实现的。


🧠 核心原理:那张二维码里到底藏了什么?

首先,我们要打破一个认知误区:手机并不是直接跟电脑说话。
它们之间有一个中间人——服务器。而连接它们的纽带,就是一个全局唯一的 ID (UUID)

当你在 PC 端打开登录页时,服务器生成了一个 UUID(比如8f9a2d...),并把它做成了二维码。

  • PC 端:手里拿着这个 UUID,眼巴巴地等着服务器通知。
  • 手机端:扫码后读到了这个 UUID,告诉服务器:“我是用户 A,我授权这个 UUID 登录。”
  • 服务器:收到手机指令后,找到手持这个 UUID 的 PC 端,发个消息说:“你通过了!”

🚀 架构演进:从“轮询”到“长连接”

1. 青铜方案:HTTP 短轮询 (Short Polling)

PC 端每隔 1 秒发一个 HTTP 请求问服务器:“有人扫码了吗?”

  • 缺点:QPS 极高,服务器压力山大,且有 1 秒的延迟感。
2. 黄金方案:WebSocket 长连接

PC 端和服务器建立一条全双工的 TCP 长连接。
一旦手机扫码成功,服务器主动推送消息给 PC。

  • 优点:毫秒级同步,服务器资源消耗极低。

交互时序图:

PC浏览器业务服务器Redis缓存手机App第一阶段:获取二维码 & 建立长连接1. 请求生成登录二维码2. 生成 UUID (状态: WAITING)3. 返回 UUID 和 二维码图片4. 发起 WebSocket 连接 (携带 UUID)5. 连接成功,保持心跳第二阶段:手机扫码 & 授权6. 扫描屏幕上的二维码7. 发送确认登录请求 (UUID + UserToken)8. 校验 UserToken 合法性9. 更新 UUID 状态为 CONFIRMED10. 绑定 UserInfo 到该 UUID第三阶段:服务器主动推送11. WebSocket 推送: LoginSuccess(Token)12. 存储 Token 跳转首页PC浏览器业务服务器Redis缓存手机App

🛠️ 实战开发:Spring Boot + WebSocket 实现

1. 服务端:建立 WebSocket 通道

我们需要维护一个ConcurrentHashMap,用于存储UUID -> WebSocketSession的映射关系,这样服务器才能根据 UUID 找到对应的 PC 连接。

@ServerEndpoint("/ws/login/{uuid}")@ComponentpublicclassQrCodeWebSocket{// 存储在线连接:Key=UUID, Value=SessionprivatestaticfinalMap<String,Session>SESSIONS=newConcurrentHashMap<>();@OnOpenpublicvoidonOpen(Sessionsession,@PathParam("uuid")Stringuuid){SESSIONS.put(uuid,session);System.out.println("PC端已连接,等待扫码: "+uuid);}@OnClosepublicvoidonClose(@PathParam("uuid")Stringuuid){SESSIONS.remove(uuid);}/** * 发送消息给 PC 端 */publicstaticvoidsendMessage(Stringuuid,Stringmessage){Sessionsession=SESSIONS.get(uuid);if(session!=null&&session.isOpen()){try{session.getBasicRemote().sendText(message);}catch(IOExceptione){e.printStackTrace();}}}}
2. 服务端:手机确认接口

当用户在手机点击“确认登录”时,调用此 HTTP 接口。

@RestController@RequestMapping("/api/login")publicclassLoginController{@PostMapping("/confirm")publicResultconfirmLogin(@RequestBodyLoginRequestrequest){Stringuuid=request.getUuid();StringuserId=request.getUserId();// 从手机端 Token 解析出来// 1. 校验 UUID 是否过期 (查 Redis)if(!redisTemplate.hasKey("qr:"+uuid)){returnResult.fail("二维码已失效");}// 2. 生成 PC 端专用的临时 TokenStringpcToken=jwtService.createToken(userId);// 3. 【核心步骤】通过 WebSocket 通知 PC 端// 构造消息体Stringmessage=newJSONObject().put("code",200).put("type","LOGIN_SUCCESS").put("token",pcToken).toString();QrCodeWebSocket.sendMessage(uuid,message);returnResult.success();}}
3. 前端:PC 网页端逻辑
// 生成 UUID 后constuuid="8f9a2d...";constws=newWebSocket("ws://localhost:8080/ws/login/"+uuid);ws.onmessage=function(event){constdata=JSON.parse(event.data);if(data.type==="LOGIN_SUCCESS"){console.log("手机确认了!跳转首页...");localStorage.setItem("token",data.token);window.location.href="/index";}};ws.onclose=function(){console.log("二维码已过期,请刷新");};

🛡️ 安全性思考:二维码被截获了怎么办?

如果黑客把你的二维码截图发给他自己,他扫了,你的电脑岂不是登录了他的号?或者反过来,你扫了黑客的码,黑客在异地登录了你的号?

这就是QRLacking(二维码劫持)攻击。
防御策略:

  1. 一次性 Token:WebSocket 推送给 PC 的 Token 应该是短效的(如 30 秒有效),PC 端拿到后必须立刻换取长效 Token。
  2. 二次确认:手机端扫码后,必须在界面上显示“即将登录 Windows Chrome 浏览器,IP 地址:上海”,让用户肉眼确认是否是本人操作。
  3. 状态绑定:Redis 中的 UUID 状态机设计:WAITING(等待扫码) ->SCANNED(已扫码,手机端显示头像) ->CONFIRMED(已确认)。

📝 总结

“扫码登录”看似简单,实则是HTTP、WebSocket、Redis、安全认证多种技术的综合应用。

  • UUID是信物。
  • Redis是状态公告栏。
  • WebSocket是直通专线。

掌握了这套机制,你不仅能做扫码登录,还能做扫码支付、扫码投屏、多屏互动等各种好玩的功能。


博主留言:
你的项目里还在用轮询做状态同步吗?
在评论区回复“WS”,我发给你一份《Spring Boot WebSocket 完美整合包(含心跳检测 + 断线重连)》,助你打造丝滑的实时应用!

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

基于单片机的PID调节脉动真空灭菌器上位机远程监控设计

基于单片机的PID调节脉动真空灭菌器上位机远程监控设计概述 点击链接下载设计资料&#xff1a;https://download.csdn.net/download/qq_39020934/92091240 1.1 研究背景与设计意义 脉动真空灭菌器广泛应用于医疗器械、生物实验室以及制药行业&#xff0c;是保证器械和材料无菌…

作者头像 李华
网站建设 2026/5/9 2:54:13

每日一个C++知识点|异步编程

上篇文章说到C多线程的基础知识, 这篇文章主要说C多线程的另一个重要知识–异步 异步 那么什么是异步呢? 当程序执行一个耗时任务的时候, 主线程硬生生等待线程任务结束,不仅效率低, 还会让程序响应变得卡顿 这时候我们可以使用异步编程来解决这个问题,异步编程的核心就是非阻…

作者头像 李华
网站建设 2026/5/10 19:40:26

探索非线性电液伺服系统:基于ESO的反步滑模控制之旅

非线性电液伺服系统&#xff0c;基于ESO(扩张状态观测器)的反步滑模控制。 pdf教程matlab/simulink源程序。 s—函数搭建 1.通过扩展状态观测器估计速度、加速度和总扰动; 2.根据在线估计的系统模型&#xff0c;设计包含反步控制和滑模控制的控制率&#xff0c;对实际系统进行控…

作者头像 李华
网站建设 2026/5/10 13:22:50

详谈:解释器模式(二)

接上文。看到这个需求&#xff0c;我们很容易想到一种写法&#xff1a;将输入的字符串分割成单个字符&#xff0c;把数字字符通过switch-case转换为数字&#xff0c;再通过计算符判断是加法还是减法&#xff0c;对应做加、减计算&#xff0c;最后返回结果即可。计划的确可行&am…

作者头像 李华
网站建设 2026/5/9 2:51:52

Redis缓存三大问题详解:击穿、穿透与雪崩的解决方案

在使用 Redis 作为缓存层时&#xff0c;我们经常会遇到三个经典问题&#xff1a;缓存击穿、缓存穿透和缓存雪崩。这些问题可能导致系统性能下降甚至崩溃&#xff0c;本文将详细介绍这三个问题的原因和解决方案。一、&#x1f3af; 缓存击穿问题描述&#xff1a;某个热点 key 在…

作者头像 李华
网站建设 2026/5/12 4:07:51

Java赋能AI智能采编:让百万传媒人提早下班的行业变革方案

Java赋能AI智能采编&#xff1a;让百万传媒人提早下班的行业变革方案 在信息爆炸的今天&#xff0c;传媒行业正面临着“素材多到理不清、稿件改到熬大夜、发布急到踩deadline”的普遍困境。数百万传媒从业者坚守在出版、新闻、广播等岗位上&#xff0c;支撑着年产值超2.5万亿元…

作者头像 李华