在很多情況下,網(wǎng)站的訪問都需要用戶登錄,要想通過程序獲取頁面信息(比如說爬蟲)就必須通過模擬登錄來實(shí)現(xiàn)。下面是我對(duì)新浪微博的模擬登錄的一些研究。
利用HttpFox監(jiān)視并且分析所有進(jìn)出瀏覽器的HTTP網(wǎng)絡(luò)傳輸。HttpFox是FireFox瀏覽器的一個(gè)插件,監(jiān)視Http網(wǎng)絡(luò)數(shù)據(jù)傳輸很方便。請(qǐng)求的數(shù)據(jù)包括:
(1) 請(qǐng)求和響應(yīng)頭數(shù)據(jù)
(2) 發(fā)送和接收的Cookie
(3) 查詢Query的各項(xiàng)參數(shù)
(4) POST的參數(shù)和數(shù)據(jù)
(5) 響應(yīng)Body數(shù)據(jù)
(6) ......
監(jiān)視新浪微博登錄時(shí)和服務(wù)器的數(shù)據(jù)傳輸情況。如圖1所示
圖 1 登錄新浪微博Http網(wǎng)絡(luò)傳輸數(shù)據(jù)
(1) 分析登錄過程,在提交POST請(qǐng)求之前,進(jìn)行了兩次GET請(qǐng)求,第二次GET請(qǐng)根據(jù)瀏覽器的不同傳遞不同數(shù)據(jù),沒意義。如圖1第一次GET請(qǐng)求地址是:http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=c3dqdHV6dyU0MGdtYWlsLmNvbQ%3D%3D&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.5)&_=1370244920303
如圖5-1下部分。得知返回?cái)?shù)據(jù):sinaSSOController.preloginCallBack({"retcode":0,"servertime":1370244920,"pcid":
"xd-fec4e580e9a32b605d0027a0269d765d05a9","nonce":"IFO817","pubkey":
"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","showpin":0,"exectime":8})
整理數(shù)據(jù)如表1 所示
表1 第一個(gè)GET請(qǐng)求返回?cái)?shù)據(jù)
參數(shù)名
值
retcode
0
servertime
1370244920
pcid
xd-fec4e580e9a32b605d0027a0269d765d05a9
nonce
IFO817
pubkey
EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E
7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFF
B38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6
442443
rsakv
1330428213
showpin
0
exectime
8
經(jīng)查詢資料,表1中有兩個(gè)重要參數(shù)“servertime”和“nonce”,其他為固定值。
(2) 觀察POST請(qǐng)求:
如圖5-2所示可知POST請(qǐng)求的數(shù)據(jù)包括的一些信息。
圖2 POST數(shù)據(jù)包參數(shù)和值
其中“su”為用戶名,它經(jīng)過BASE64計(jì)算?!皊p”為密碼,其加密方法為:
先創(chuàng)建一個(gè)rsa公鑰,公鑰的兩個(gè)參數(shù)新浪微博都給了固定值,不過給的都是16進(jìn)制的字符串,第一個(gè)是登錄第一步中的pubkey(見表1),第二個(gè)是js加密文件中的‘10001’。這兩個(gè)值需要先從16進(jìn)制轉(zhuǎn)換成10進(jìn)制。然后再servertime加上nonce加上用戶密碼進(jìn)行RSA加密。
(3) 模擬登錄
通過研究新浪微博登錄的過程,就可以偽造一個(gè)HttpClient實(shí)例進(jìn)行登錄了。
①構(gòu)造一個(gè)HttpClient實(shí)例:
DefaultHttpClient client = new DefaultHttpClient();
②構(gòu)造第一個(gè)登錄請(qǐng)求:獲取servertime和nonce的值。
③對(duì)用戶名和密碼進(jìn)行加密
String pwdString = servertime + "\t" + nonce +"\n" + "pwd";
sp = new BigIntegerRSA().rsaCrypt(SINA_PK,"10001",pwdString);
④構(gòu)造POST數(shù)據(jù)包。
HttpPost post = new HttpPost( "http://login.sina.com.cn/sso/login.php?client=ssologin.js (v 1.4.2)");
……
post.setEntity(newUrlEncodedFormEntity(nvps, HTTP.UTF_8)); ①
⑤執(zhí)行POST請(qǐng)求。
HttpResponse response=null;
……
response= client.execute(post);
⑥獲取實(shí)際URL,并請(qǐng)求該URL。
String entity=null;
……
entity =EntityUtils.toString(response.getEntity());
……
String url =entity.substring(
entity.indexOf("http://weibo.com/sso/login.php?"),
entity.indexOf("code=0")+ 6); // 獲取到實(shí)際url進(jìn)行連接
HttpGet getMethod= new HttpGet(url);
……
response =client.execute(getMethod);
⑦獲取Cookie。
CookieStore cookie = client.getCookieStore();
通過以上步驟模擬登錄就處理完了,可以通過最后獲取的Cookie信息進(jìn)行新浪微博頁面的訪問,只需要在請(qǐng)求頁面的時(shí)候?qū)⒋薈ookie發(fā)送過去身份認(rèn)證就完成了。通過身份認(rèn)證就可以對(duì)新浪微博的頁面進(jìn)行訪問了。