扫码登录的本质:一场三方接力
扫码登录协议的设计目标是"用已登录的 App 给无登录态的 web 端授权"。参与三方:web 端(展示二维码)、App 端(扫码确认)、服务端(状态仲裁)。整个流程是一场状态机接力:
web 生成二维码(含 token) → 轮询状态
↓
App 扫码 → 解析出 token → 带 App 登录态请求"确认登录"
↓
服务端确认后 → web 轮询到"已确认" → 换取登录 cookie逆向的关键是搞清楚每个状态的接口和参数。
抖音 web 端扫码流程实测
第一步:获取二维码
GET https://sso.douyin.com/get_qrcode/?service=https://www.douyin.com&...返回二维码内容(一个 URL,内含 token 字段)和二维码图片。token 是这场接力的接力棒,有效期约 3-5 分钟。
第二步:轮询状态
GET https://sso.douyin.com/check_qrconnect/?token=xxx&...状态机:0=等待扫码,1=已扫码待确认,2=已确认,3=已过期。轮询间隔 1-2 秒,别太激进。
第三步:确认后换 cookie
状态变 2 后,响应里带 redirect_url,跟着跳转链走,最终 Set-Cookie 种下 sessionid、sessionid_ss 等登录 cookie——web 端登录完成。
App 侧:扫码确认请求怎么构造
协议模拟的完整闭环需要 App 侧配合(用 App 的登录态去"确认")。抓 App 扫码后的请求:
POST https://sso.douyin.com/scan_qrcode/ (或类似端点)
Cookie: sessionid=xxx (App 的登录态)
Body: token=xxx&action=confirm工程上两种玩法:
- 人工扫码:协议程序生成二维码展示出来,用真实手机抖音扫码——半自动,适合给自己用
- 协议确认:维护一批 App 登录态(sessionid 池),程序解析二维码 token 后直接构造确认请求——全自动,适合批量
精髓:四个实战坑
- 二维码 token 一次性且短效。确认后 token 即作废,过期要重新生成。轮询到状态 3 要自动重新走第一步
- web 端的 cookie 和 App 端不通用。
sessionid(web)和 App 内的登录态是两套体系,别混用 - 轮询频率有风控。每秒 1 次是安全线,再快会触发
check_qrconnect的限流(返回错误码或直接封 IP 几分钟) - redirect 链要完整走。确认后的跳转链有 2-3 跳,每一跳都种 cookie,用
requests.Session自动跟跳转,别手动只跟最后一跳——会漏 cookie
完整代码骨架
import requests, time, re, json
class DouyinQRLogin:
def __init__(self):
self.s = requests.Session()
self.s.headers['User-Agent'] = 'Mozilla/5.0 ...'
def get_qrcode(self):
r = self.s.get('https://sso.douyin.com/get_qrcode/',
params={'service': 'https://www.douyin.com', 'need_logo': 'false'})
data = r.json()['data']
self.token = data['token']
return data['qrcode_index_url'] # 二维码图片地址
def poll(self, timeout=180):
deadline = time.time() + timeout
while time.time() < deadline:
r = self.s.get('https://sso.douyin.com/check_qrconnect/',
params={'token': self.token, 'service': 'https://www.douyin.com'})
data = r.json()['data']
status = data.get('status')
if status == '2' or data.get('error_code') == 0 and 'redirect_url' in data:
self.s.get(data['redirect_url']) # 跟跳转链拿 cookie
return True
if status == '3':
return False # 过期
time.sleep(1.5)
return False总结
- 扫码登录 = 二维码 token + 状态轮询 + 确认换 cookie 的三方接力
- 抖音端点:get_qrcode → check_qrconnect → redirect 链
- 自动化两条路:人工扫码半自动,App 登录态池全自动
- token 一次性短效,轮询控速 1.5s,redirect 链走完整
交流微信:run1255