文章总结: 本文详细解析了扫码登录的两种核心场景:同平台登录(如PC端登录)和第三方平台登录(如用账号A登录应用B)。同平台场景下,PC端通过服务端获取含ticket的二维码,手机扫码确认后服务端返回sessionid完成登录。第三方场景基于OAuth2.0协议,通过授权码和accesstoken实现安全授权,确保用户密码不泄露。文章强调二维码仅作为信息载体,真正验证在服务端完成,并对比了两种场景的协议差异。 综合评分: 88 文章分类: WEB安全,安全开发,安全建设,解决方案,实战经验
面试官:扫码登录时手机是如何把登录态“传”给电脑的?
Ray Ray
Ray.s Sandbox
2026年7月7日 18:30 湖北
在小说阅读器读本章
去阅读
一、背景
扫码登录的核心思想:
PC端:我需要登录,请验证我的身份
↓
手机端:我是这个账号的主人,我确认
↓
服务端:验证通过,允许登录
二维码只是传递信息的载体,真正完成验证的是服务端。
扫码登录分为两种场景:
| 场景 | 例子 | 协议 | | — | — | — | | 同平台 | PC端登录 | 自定义协议 | | 第三方平台 | 用账号A登录应用B(如登录游戏、登录小程序) | OAuth 2.0 |
二、同平台扫码登录
2.1 什么是同平台
PC端和手机端是同一个服务的两个客户端,服务端也是同一个。
PC端 ────→ 服务端 ←──── 手机端
2.2 完整流程
┌─────────┐ ┌─────────┐ ┌─────────┐
│ PC端 │ │ 服务端 │ │ 手机端 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ 1.请求生成二维码 │ │
│ ─────────────────────────> │ │
│ │ │
│ 2.返回二维码(含ticket) │ │
│ <───────────────────────── │ │
│ │ │
│ 3.显示二维码 │ │
│ │ │
│ 4.轮询等待扫码结果 │ │
│ ─────────────────────────> │ │
│ │ │
│ │ 5.手机扫码获取ticket │
│ │ <───────────────────────── │
│ │ │
│ │ 6.手机确认登录 │
│ │ <───────────────────────── │
│ │ │
│ 7.轮询返回session_id │ │
│ <───────────────────────── │ │
│ │ │
2.3 分步解析
Step 1-2:生成二维码
PC端向服务端请求生成二维码,服务端返回一个包含 ticket 的 URL:
GET /api/qrcode/generate
Response: {
"ticket": "abc123def456",
"url": "https://login.example.com/qr?ticket=abc123def456"
}
ticket 是一个随机字符串,用于标识这次扫码请求。
Step 3:显示二维码
PC端将这个 URL 编码成二维码图片显示给用户。
Step 4:轮询状态
PC端不断向服务端查询这个 ticket 的状态:
GET /api/qrcode/status?ticket=abc123def456
返回状态:
- pending: 等待扫码
- scanned: 已扫码,等待确认
- confirmed: 已确认,登录成功
- expired: 二维码已过期
Step 5-6:手机扫码确认
手机端扫描二维码,获取 ticket,向服务端发送确认请求:
POST /api/qrcode/confirm
Body: {
"ticket": "abc123def456",
"user_token": "手机端当前的登录态"
}
服务端验证:
- ticket 是否有效?
- 手机端的登录态是否有效?
Step 7:返回登录凭证
服务端生成一个 session_id,返回给PC端:
Response: {
"status": "confirmed",
"session_id": "xyz789"
}
PC端拿到 session_id,登录完成。
三、OAuth 的原理
3.1 为什么需要 OAuth
当两个不同的服务需要共享身份认证时,不能直接传递密码,需要一个标准化的授权协议。
OAuth 解决的问题:
| 问题 | 说明 | | — | — | | 身份隔离 | 第三方不能获取用户密码 | | 权限控制 | 只能获取用户授权的信息 | | 安全边界 | 一方出问题不影响另一方 |
3.2 OAuth 核心概念
| 概念 | 说明 | | — | — | | Resource Owner | 用户本人 | | Client | 第三方应用 | | Authorization Server | 授权服务器 | | Resource Server | 资源服务器 | | Authorization Code | 临时授权凭证 | | Access Token | 访问令牌,用于获取资源 |
3.3 标准流程
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Client │ │ Auth │ │ Resource│
│ │ │ Server │ │ Owner │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ 1.请求授权 │ │
│ ───────────────> │ │
│ │ 2.询问用户是否授权 │
│ │ ───────────────> │
│ │ │
│ │ 3.用户确认授权 │
│ │ <─────────────── │
│ │ │
│ 4.返回授权码 │ │
│ <─────────────── │ │
│ │ │
│ 5.用授权码换token │ │
│ ───────────────> │ │
│ │ │
│ 6.返回access_token│ │
│ <─────────────── │ │
│ │ │
│ 7.用token获取资源 │ │
│ ──────────────────────────────────> │
│ │ │
│ 8.返回资源 │ │
│ <────────────────────────────────── │
3.4 授权码的作用
授权码是一个临时凭证,用于换取 access_token:
Client → Auth Server: "用户授权了,给我access_token"
Auth Server → Client: "这是access_token,有效期7天"
为什么需要授权码,而不是直接给 token? title: “扫码登录的原理” date: “2025-07-07”
| 直接给token | 先给授权码 | | — | — | | token暴露在前端 | token只在后端传递 | | 容易被截获 | 更安全 | | 无法撤销 | 可以撤销授权 |
3.5 Access Token 详解
| 属性 | 说明 | | — | — | | 本质 | 一个临时的字符串凭证 | | 作用 | 证明”用户授权了我”,可以用它调用API | | 有效期 | 通常7天,过期需要刷新 | | 权限范围 | 只能获取用户授权的信息 |
没有 access_token:
第三方应用 → 授权服务器:把用户密码给我
授权服务器 → 第三方应用:不行,太危险
有 access_token:
第三方应用 → 授权服务器:这是用户给我的授权码
授权服务器 → 第三方应用:好的,这是用户的标识
四、第三方平台扫码登录
4.1 什么是第三方平台
PC端(或应用)和手机端属于不同的服务,需要借助第三方的身份验证。
应用B客户端 ──→ 应用B服务端 ──→ 账号A的OAuth服务端 ←── 账号A手机端
4.2 完整流程
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 应用B │ │ B服务端 │ │ A的OAuth │ │ A手机端 │
│ 客户端 │ │ │ │ │ │ │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │
│ 1.点击"账号A登录" │ │ │
│ ──────────────> │ │ │
│ │ 2.申请授权二维码 │ │
│ │ ───────────────> │ │
│ │ 3.返回二维码URL │ │
│ │ + session_key │ │
│ │ <─────────────── │ │
│ 4.显示二维码 │ │ │
│ <───────────── │ │ │
│ │ │ │
│ │ 5.轮询扫码状态 │ │
│ │ ───────────────> │ │
│ │ │ 6.手机扫码 │
│ │ │ <────────────── │
│ │ │ │
│ │ │ 7.手机确认 │
│ │ │ <────────────── │
│ │ │ │
│ │ 8.轮询返回已确认 │ │
│ │ + auth_code │ │
│ │ <─────────────── │ │
│ │ │ │
│ │ 9.用code换token │ │
│ │ ───────────────> │ │
│ │ 10.返回access_token│ │
│ │ <─────────────── │ │
│ │ │ │
│ │ 11.获取用户信息 │ │
│ │ ───────────────> │ │
│ │ 12.返回用户标识 │ │
│ │ <─────────────── │ │
│ │ │ │
│ 13.登录成功 │ │ │
│ <───────────── │ │ │
4.3 分步解析
Step 1-4:发起授权请求
应用B客户端向自己的服务端发起请求,服务端向账号A的OAuth申请授权二维码。
GET https://auth.accountA.com/oauth/authorize?
client_id=应用B的AppID&
redirect_uri=https://appB.com/callback&
response_type=code&
state=随机字符串
Step 5-8:扫码确认
应用B服务端拿着 session_key 轮询账号A的OAuth状态接口:
GET https://auth.accountA.com/oauth/status?session_key=xxx
返回状态:
- pending: 等待扫码
- scanned: 已扫码,等待确认
- confirmed: 已确认,返回authorization_code
用户扫码确认后,账号A的OAuth返回一个 authorization_code。
Step 9-10:换取 Access Token
应用B服务端用 authorization_code 换取 access_token:
POST https://auth.accountA.com/oauth/access_token
Body: {
"client_id": "应用B的AppID",
"client_secret": "应用B的密钥",
"code": "authorization_code",
"grant_type": "authorization_code"
}
Response: {
"access_token": "xxx",
"expires_in": 7776000
}
Step 11-12:获取用户信息
应用B用 access_token 获取用户的标识:
GET https://api.accountA.com/oauth/me?access_token=xxx
Response: {
"user_id": "用户唯一标识",
"nickname": "用户昵称"
}
Step 13:登录完成
应用B用自己的服务端,根据用户标识创建/关联账号,签发应用内的 session。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Ray.s Sandbox Ray Ray《面试官:扫码登录时手机是如何把登录态“传”给电脑的?》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论