QQ空间扫码登录协议实现
从0实现QQ空间二维码登录,逆向ptqrtoken、login_sig参数算法
JS/爬虫逆向玩转qq空间协议保姆级教学—二维码登录篇
二维码登录和账号密码登录很像,几乎可以说是账号密码登录的简化版
了解账号密码登录之后再来看二维码登录易如反掌
账号密码登录教学请点下方蓝色字体
结尾附Python代码
登录协议——QQ空间登录协议逆向分析|账号密码登录
目录
一、抓包、参数分析
1.1数据包1——二维码包
通过GET请求这个数据包,即可获得二维码,同时Cookie中获得参数
qrsig
1.2数据包——2 login_sig
https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&=&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=手机QQ空间&pt_qr_link=https://z.qzone.com/download.html&self_regurl=https://qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=https://z.qzone.com/download.html&pt_no_auth=0
GET请求上面的URL,即可在Cookie获得login_sig
以及pt_clientip、pt_guid_sig、pt_local_token、pt_login_sig、pt_serverip、 pt_user_id、ptui_identifier、uikey
1.3数据包3——登录状态包
https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&ptqrtoken=1251677953&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-6-1726759691918&js_ver=24090913&js_type=1&login_sig=gRa0dbFM2zvBBtBq7SsT-5zMNE8-*kvEBcmL2j206E3ifj9cEsSt0RauGnlIcaHX&pt_uistyle=40&aid=549000912&daid=5&=&o1vId=2b82096ccefcae244d20335bbe82233c&pt_js_version=e8983a1a
ptqrtoken——通过qrsig计算得来
login_sig——访问数据包2后Cookie中获取
重复循环GET请求读取响应,扫码成功登陆后这个包会像账号密码登录时一样响应一个check url
ptuiCB('0','0','https://ptlogin2.qzone.qq.com/check_sig?pttype=1&uin=QQ号&service=ptqrlogin&nodirect=0&ptsigx=XXXd&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&f_url=&ptlang=2052&ptredirect=100&aid=549000912&daid=5&j_later=0&low_login_hour=0®master=0&pt_login_type=3&pt_aid=0&pt_aaid=16&pt_light=0&pt_3rd_aid=0','0', '登陆成功','QQ昵称');
1.4数据包4——登录成功check包
利用数据包3响应的check url 通过之前的数据包保存的Cookie进行GET请求即可成功获取最终登录的Cookie
二、算法逆向
前面知道ptqrtoken是通过qrsig计算得来
通过我的文章 QQ空间协议分析|账号密码登录
可以知道直接搜索ptqrtoken即可发现是通过hash33函数进行加密得到,参数就是qrsig
直接搜索hash33即可找到加密函数,函数参数t就是qrsig
三、Python代码实现
4.1 ptqrtoken算法
ptqrtoken算法代码较为简单,直接扣下来即可
def hash33(t): #参数:qrsig
e = 0
for n in range(len(t)):
e = (e << 5) + ord(t[n])
return e & 2147483647 # 返回ptqrtoken
4.2发包代码
保存二维码
def get_qr_image_with_cookies(cookies, headers): #保存二维码
global global_cookies
# 设置二维码请求的 URL
qr_url = "https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.39175954831717164&daid=5&pt_3rd_aid=0&u1=https://qzs.qzone.qq.com/qzone/v5/loginsucc.html?para=izone"
# 为二维码请求设置新的请求头
headers.update({
"Host": "ssl.ptlogin2.qq.com",
"Accept": "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5",
"Referer": "https://xui.ptlogin2.qq.com/",
"Sec-Fetch-Dest": "image",
"Sec-Fetch-Mode": "no-cors",
"Sec-Fetch-Site": "same-site",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
})
# 发送带有请求头和 Cookie 的请求以获取二维码
response = requests.get(qr_url, headers=headers, cookies=cookies)
# 检查请求是否成功
if response.status_code == 200:
# 保存二维码图片到本地
with open("qrcode_with_new_cookie.png", "wb") as f:
f.write(response.content)
print("二维码已成功保存为 'qrcode_with_new_cookie.png'")
# 打印新获取的 Cookie
'''print("新获取的 Cookie:")
for cookie in response.cookies:
print(f"{cookie.name}: {cookie.value}")'''
# 将新获取的 Cookie 合并到全局的 Cookie 中
global_cookies.update(response.cookies)
else:
print(f"二维码请求失败,状态码:{response.status_code}")
获取login_sig
def get_initial_cookies():
global global_cookies
# 发送 GET 请求到指定的 URL 来获取初始 Cookie
url = "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&=&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https://qzs.qqzone.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=手机QQ空间&pt_qr_link=http://z.qzone.com/download.html&self_regurl=https://qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http://z.qzone.com/download.html&pt_no_auth=1"
headers = {
"Host": "xui.ptlogin2.qq.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Cache-Control": "max-age=0"
}
# 发起 GET 请求
response = requests.get(url, headers=headers)
# 检查请求是否成功
if response.status_code == 200:
# 合并获取的 Cookie 到全局变量中
global_cookies.update(response.cookies)
return global_cookies, headers
else:
print(f"请求失败,状态码:{response.status_code}")
return None, None
其他代码同理使用GET请求,修改一下URL
只需要注意更新Cookie,把新Cookie和旧Cookie合并即可