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. 实现效果

QQ快速登录协议分析与实现

3.具体代码

更详细的代码可参考:https://github.com/pibigstar/go-demo/blob/...  

本项目包含了 Go 常用的设计模式、Go 面试易错点、简单的小项目(区块链,爬虫等)、还有各种第三方的对接(redis、sms、nsq、elsticsearch、alipay、oss...),如果对你有所帮助,请给个 Star,你的支持,是我最大的动力!

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!