QQ 快速登入協議分析與實現

pibigstar發表於2019-09-14

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

QQ快速登入協議分析與實現

更詳細的程式碼可參考:https://github.com/pibigstar/go-demo/blob/...  

本專案包含了 Go 常用的設計模式、Go 面試易錯點、簡單的小專案(區塊鏈,爬蟲等)、還有各種第三方的對接(redis、sms、nsq、elsticsearch、alipay、oss...),如果對你有所幫助,請給個 Star,你的支援,是我最大的動力!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章