QQ 快速登录协议分析与实现
1. QQ快速登录协议分析
1.1 获取pt_local_token
req, _ := http.NewRequest("GET", "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?s_url="+targetUrl+"&style=20&appid=715021417&proxy_url=https%3A%2F%2Fhuifu.qq.com%2Fproxy.html", nil)
response, err := client.Do(req)
if err != nil {
fmt.Printf("第一次请求失败:status:%s, err:%s \n", response.Status, err.Error())
}
ptLocalToken := processStr(response.Header["Set-Cookie"], "pt_local_token")
user.PtLocalToken = ptLocalToken
1.2 获取本机登录的QQ号
flag := false
for i := 0; i < 8; i++ {
req, _ = http.NewRequest("GET", fmt.Sprintf("https://localhost.ptlogin2.qq.com:430%d/pt_get_uins?callback=ptui_getuins_CB&r=0.6694805047494219&pt_local_tk=%s", i, ptLocalToken), nil)
req.Header.Set("cookie", fmt.Sprintf("pt_local_token=%s", ptLocalToken))
req.Header.Set("referer", referer)
res, err := client.Do(req)
if err != nil || res == nil {
//fmt.Printf("端口430%d 无法连接\n",i)
continue
} else {
bytes, _ := ioutil.ReadAll(res.Body)
body := string(bytes)
r := regexp.MustCompile("\\[.*?]")
temp := string(r.Find([]byte(body)))
temp = temp[1 : len(temp)-1]
json.Unmarshal([]byte(temp), &user)
flag = true
break
}
}
if !flag {
return
}
1.3 获取clientkey
req, _ = http.NewRequest("GET", fmt.Sprintf("https://localhost.ptlogin2.qq.com:4301/pt_get_st?clientuin=%s&callback=ptui_getst_CB&r=0.7284667321181328&pt_local_tk=%s", user.Account, ptLocalToken), nil)
req.Header.Set("cookie", fmt.Sprintf("pt_local_token=%s", ptLocalToken))
req.Header.Set("referer", referer)
res, err := client.Do(req)
if err != nil {
fmt.Printf("第三次请求失败:status:%s, err:%s \n", res.Status, err.Error())
}
clientkey := processStr(res.Header["Set-Cookie"], "clientkey")
1.4 获取skey
url := "https://ptlogin2.qq.com/jump?clientuin=" + user.Account + "&keyindex=9&pt_aid=549000912&daid=5&u1=" + targetUrl + "%3Fpara%3Dizone&pt_local_tk=" + ptLocalToken + "&pt_3rd_aid=0&ptopt=1&style=40&has_onekey=1"
req, _ = http.NewRequest("GET", url, nil)
req.Header.Set("cookie", fmt.Sprintf("pt_local_token=%s;clientuin=%s;clientkey=%s", ptLocalToken, user.Account, clientkey))
req.Header.Set("referer", referer)
res, err = client.Do(req)
if err != nil {
fmt.Printf("第四次请求失败:status:%s, err:%s \n", res.Status, err.Error())
}
uin := processStr(res.Header["Set-Cookie"], "uin")
skey := processStr(res.Header["Set-Cookie"], "skey")
user.Uin = uin
user.Skey = skey
// 获取返回的URL
all, _ := ioutil.ReadAll(res.Body)
temp := string(all)
r := regexp.MustCompile("https(.*?)'")
temp = string(r.Find([]byte(temp)))
url = temp[0 : len(temp)-1]
1.5 根据第四步返回的URL,获取p_skey
req, _ = http.NewRequest("GET", url, nil)
req.Header.Set("cookie", fmt.Sprintf("pt_local_token=%s", ptLocalToken))
req.Header.Set("referer", referer)
res, err = client.Do(req)
if err != nil {
fmt.Printf("第五次请求失败:status:%s, err:%s \n", res.Status, err.Error())
}
pSkey := processStr(res.Request.Response.Header["Set-Cookie"], "p_skey")
user.PSkey = pSkey
user.GTK = genderGTK(skey)
至此skey 和 p_skey我们就都拿到了,这两个东西相当于QQ空间的token
2. 实现效果
3.具体代码
更详细的代码可参考:https://github.com/pibigstar/go-demo/blob/...
本项目包含了 Go 常用的设计模式、Go 面试易错点、简单的小项目(区块链,爬虫等)、还有各种第三方的对接(redis、sms、nsq、elsticsearch、alipay、oss...),如果对你有所帮助,请给个 Star
,你的支持,是我最大的动力!
本作品采用《CC 协议》,转载必须注明作者和本文链接