发送http GET请求:
https://ui.ptlogin2.qq.com/cgi-bin/login?daid=164&target=self&style=5&mibao_css=m_webqq&appid=1003903&enable_qlogin=0&no_verifyimg=1&s_url=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html&f_url=loginerroralert&strong_login=1&login_state=10&t=20130830001
在响应的HTML中通过正则表达式 /var g_login_sig=encodeURIComponent\(“(.+?)”\);/)获取到安全参数sign.
在上面的URL中,有个参数要注意 appid=1003903这个参数在下面的步骤中经常遇到.
首先检验是否需要输入验证码
发送HTTP GET请求
”https://ssl.ptlogin2.qq.com/check?uin={0}&appid={1}&js_ver=10038&js_type=0&login_sig={2}&u1=http%3A%2F%2Fweb2.qq.com%2Floginproxy.html&r=0.5331138293443659″.format(QQ, APPID, sign);
上面的请求中,参数QQ指要登录的QQ号码,APPID始终为1003903,sign是上步中获取到的安全参数.
响应类似于下面的格式:
pt_checkVC('0', '!B55', '\x00\x00\x00\x00\xa6\xce\xef\xfe') 如果第一个数字为0,则表示第二个参数做为验证码;如果为1,则表示要通过图片输入验证码,验证码图片的请求如下:
发送https GET请求
“https://ssl.captcha.qq.com/getimage?aid={0}&r={1}&uin={2}”.format(APPID, Math.random(), QQ)
获取图片后可以得到验证码.
发送https GET请求:
‘https://ssl.ptlogin2.qq.com/login?u={0}&p={1}&verifycode={2}&webqq_type=10&remember_uin=1&login2qq=1&aid={3}&u1={4}&h=1&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=1-41-15424&mibao_css=m_webqq&t=1&g=1&js_type=0&js_ver=10038&login_sig={5}’.format(QQ, p, vc, APPID, “http%3A%2F%2Fweb.qq.com%2Floginproxy.html%3Flogin2qq%3D1%26webqq_type%3D10″, sign);
参数QQ指QQ号,p指加密后的密码,vc是验证码.
该请求必须设置Refer为:’https://ui.ptlogin2.qq.com/cgi-bin/login?daid=164′.
如果登录成功,会返回ptuiCB('0',....),从返回的cookie中取出ptwebqq.
密码的加密算法在js中,地址是:https://ui.ptlogin2.qq.com/js/10043/comm.js?ptui_identifier=000E012E3A89FB8098A4F8D0E9B21E4FF2947BF9AD24272D7C18A9AC29
加密算法的大致如下:
function getEncPass(q, p, v){
var I = hexchar2bin(md5(p));
var H = md5(I + hexchar2bin(pad(q.toString(16),16)));
return md5(H + v.toUpperCase());
}
其中,q为Q号,p为密码,v是验证码.
这步完了以后只是登录了网站,采用QQ单点认证机制的网站都可以通过的原理登录.
登录成功后返回的字符串中有一个url,以HTTP GET请求方式发送该请求,在响应中会返回两个重要的Cookie:p_skey,pt4_token
发送http POST请求:
http://d.web2.qq.com/channel/login2′
请求的headers必须设置content-type为application/x-www-form-urlencoded; charset=UTF-8, referer 为http://d.web2.qq.com/proxy.html?v=20110331002&callback=2.同时把上个请求的cookie也发送回去.
该请求的post参数有三个’{“status”:”online”,”ptwebqq”:”{0}”,”passwd_sig”:”",”clientid”:”{1}”,”psessionid”:null}’.format(PTWebQQ, ClientID);
请求会返回一个JSON格式的字符串,属性retcode为0则表示登录成功.
{"retcode":0, "result": { "uin":10897944,"cip":1959559061,"index":1075,"port":40036,"status":"online", "vfwebqq":"963856c05954b2f1a0b1f4efff16cc605ce3a1b84792ac678dee4b919c1a", "psessionid":"c53856c05954b2f1a0b1f4efff16cc605ce3a1b84792ac678dee4b919c1a","user_state":0,"f":0 } }
登录成功后,将上面JSON中的vfwebqq和psessionid取出来,供下面的请求使用.
发送HTTP POST请求
http://s.web2.qq.com/api/get_user_friends2
POST参数为:
r {“h”:”hello”,”hash”:”1FD22A64″,”vfwebqq”:”2445fac910fd4f2e1c01a5fcab36d13a024ccb75abed5360dbf6393c58670cb896bb578e86d3d9ee”}
请求headers需要设置cookie,cookie必须有三个值p_uin, p_skey, pt4_token, ptwebqq.
p_uin为字母o+QQ号的10位形式(不足10位前面补零),如o1624240747
序列化以后为’r=%7B%22h%22%3A%22hello%22%2C%22hash%22%3A%221FD22A64%22%2C%22vfwebqq%22%3A%222445fac910fd4f2e1c01a5fcab36d13a024ccb75abed5360dbf6393c58670cb896bb578e86d3d9ee%22%7D’;
hash通过js算出来的一个值,该算法经常会变,这儿就不列出来了.
请求成功后返回好友列表.
Web QQ通过不断发送poll2轮询获取好友消息
发送HTTP POST请求:
http://d.web2.qq.com/channel/poll2
POST参数
{r:’{“clientid”:”{0}”,”psessionid”:”{1}”,”key”:0,”ids”:[]}’.format(ClientID, PSessionID),clientid:ClientID, psessionid:PSessionID}
clientid为随机生成的客户端ID, 在Web QQ 所有过程中应该保持一致.
请求headers必须设置
headers : {‘content-length’:post_data.length,’content-type’:'application/x-www-form-urlencoded; charset=UTF-8′,referer : ‘http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=3′},
cookie不需要
请求返回一个JSON字符串
{"retcode":0,"result":[{"poll_type":"buddies_status_change","value":{"uin":3983012188,"status":"online","client_type":1}}]}
retcode为0表示获取成功.
poll_type这儿列举几种可能的值: message : 正常的消息 kick_message : 被踢下线 buddies_status_change : 好友在线状态改变 input_notify : 正在输入 tips : 提示信息 各种消息的构造就不说了.
发送HTTP POST请求
http://d.web2.qq.com/channel/send_buddy_msg2
post参数为
{
r : r,
clientid : ClientID,
psessionid : PSessionID
})
r为一个字符串,形式如:
‘{“to”:’ + uin +’,”face”:579,”content”:”[\\"' + result + '\\\\n\\",[\\"font\\",{\\"name\\":\\"微软雅黑\\",\\"size\\":\\"10\\",\\"style\\":[0,0,0],\\”color\\”:\\”000000\\”}]]”,”msg_id”:33470003,”clientid”:”‘+ClientID+’”,”psessionid”:”‘+PSessionID+’”}’
其中uin 指好友的临时号码,获取好友列表的时候可以取的到.
请求的headers必须设置referer为’http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=2′,不需要设置cookie