由于各种原因,登录百度获取bduss的方式越来越少了,加上某段时间百度开始限制单一机器用账号密码登录的上限,导致博主的直链解析站所依赖的budss获取站也挂了,博主一度陷入了烦恼。
百度坑死人

所以博主研究了扫码登录

关于扫码登录

这个功能很早就有了,只是博主一直没去研究,扫码登录能获取有效期长达十年的bduss,但是除了手机百度以外,其他百度系的应用都只能调用摄像头扫码,不能在图库选择图片,这意味着用户必须有两台或以上的设备才能够使用扫码登录。

获取二维码

简单的抓包就可以发现二维码获取的链接

1
curl "https://passport.baidu.com/v2/api/getqrcode?lp=pc"

然后会返回一串json,反序列化后会得到imgurlsign

1
2
3
4
5
6
{
"imgurl": "passport.baidu.com/v2/api/qrcode?sign=c2db7cc9133219a586606e9468decf3e&lp=pc",
"errno": ,
"sign": "c2db7cc9133219a586606e9468decf3e",
"prompt": "登录后威马将获得百度帐号的公开信息(用户名、头像)"
}

剩下那些就不用管了
imgurl就是获取扫码登录用的二维码,而sign是对应二维码的唯一id

不获取二维码直接使用网页授权

二维码只是一个链接,所以可以拼接链接并访问该链接授权

https://wappass.baidu.com/wp/?qrlogin=&sign=c2db7cc9133219a586606e9468decf3e

2020-03-30更新:百度不再允许pc的ua访问此链接,会提示下载手机客户端,移动ua不受影响

获取临时bduss

获得二维码时,经过简单的筛选就可以发现后台在尝试连接一个url,但只要不扫码,一段时间以后会连接超时,然后再次进行请求,周而复始……

1
curl "https://passport.baidu.com/channel/unicast?channel_id=c2db7cc9133219a586606e9468decf3e&callback="

这里的channel_id其实就是前面获取到的sign,扫了码再获取就不会超时了,不过这里有一个坑,链接里面必须要有callback,即使它没有值……
然后又有了这货

({“errno”:0,”channel_v”:”{"status":0,"v":"**********************************","u":null}”})

双重嵌套json,嗯……
那个v对应的键值就是临时的bduss

登录

https://passport.baidu.com/v3/login/main/qrbdusslogin?bduss=[刚才获取到的临时bduss]

简单的GET请求,不是么?
然后就可以在返回头那的set-cookie拿你想拿的东西了

心血来潮去看了一下cookie以外返回了些啥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"errInfo": {
"no": "0",
"msg": ""
},
"code": "110000",
"message": "",
'data': {
"u": "https:\/\/passport.baidu.com\/",
"userName": "",
"hao123Param": "******FBQUFBQUFBQUFBQU******",
"bdusssign": "",
"authtoken": "",
"session": {
"version": "v3",
"actionType": "",
"canshare": "1",
"authsid": "******",
"needvcode": "0",
"bduss": "******AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA******",
"ptoken": "******",
"stoken": "******",
"ubi": "******",
"stokenList": "[\"tb#******\",\"pp#******\",\"bp#******\",\"netdisk#******\",\"cloudforbusiness#******\",\"bdwm#******\",\"waimai#******\",\"bdwalletsdk#******\",\"baiduwalletapp#******\",\"baidugushitong#******\",\"bdbus#******\",\"fund#******\",\"nuomi#******\",\"licai#******\",\"asset#******\",\"hao123#******\",\"pcs#******\",\"dev#******\",\"fbuym#******\",\"licaiapp#******\",\"mybox#******\",\"iitnightingale#******\",\"dianying#******\",\"mall#******\",\"lv#******\",\"cmovie#******\",\"mapsafe#******\",\"im_hi#******\","ppapp#******\",\"licaient#******\",\"album#******\",\"aduqa#******\"]"
},
"user": {
"username": "******",
"weakpass": "",
"userId": "1",
"livinguname": "",
"portraitUrl": "https:\/\/himg.bdimg.com\/sys\/portrait\/item\/pp.1.******.******.jpg",
"portraitSign": "pp.1.******.******",
"displayName": "******"
}
},
"traceid": ""
}

还挺详细的,json部分标红是百度的问题,这不是一个标准的json,使用了单引号 ' 以及加多了一个反斜杠 \, 所以直接使用 JSON.parse()json_decode() 会报错,可以预处理一遍字符串 ("是双引号 ")

1
str.replace(/'([^'']+)'/gm, `"$1"`)).replace(/\\&/gm, "&")
1
preg_replace("/'([^'']+)'/", '"$1"', str_replace("\\&", "&", $str))

由于百度每种服务所需要的stoken都不同,这里一次性列出所有stoken stokenList 还是挺方便的

后记

本来很简单的事情研究了一早上,因为curl忘记加上RETURNTRANSFER,被自己蠢哭(逃ε=ε=ε=┏(゜ロ゜;)┛
demo在此,你们要的蓝色的东西https://bduss.nest.moe/

2020-03-30追记:我以前都写了些啥啊

评论