目前有很多的SNS社區或類(lèi)SNS的網(wǎng)站。
例如開(kāi)心、51、校內等,但是發(fā)現大多數社區在邀請好友的時(shí)候都沒(méi)有提供對QQ郵箱或者QQ空間好友列表獲取的功能,不過(guò)好像海內支持。
但是網(wǎng)上相關(guān)QQ的文章還不是很多,希望這篇文章能給你帶來(lái)一些幫助。
QQ空間及郵箱登陸的校驗方式:
QQ空間及郵箱登陸的時(shí)候。
用戶(hù)輸入的密碼首先會(huì )被頁(yè)面中的一段Js加密。
然后加密過(guò)后的密碼會(huì )加上驗證碼形成一個(gè)新的字串。
接著(zhù)這個(gè)新的字串被MD5(32位)加密。
加密過(guò)后形成最終的密碼,這就是我們?yōu)槭裁唇?jīng)常會(huì )發(fā)現我們在提交的時(shí)候我們的密碼框中的密碼個(gè)數會(huì )增長(cháng)的原因,接著(zhù)在你提交的時(shí)候,當前的這個(gè)請求會(huì )將前一次獲取驗證碼返來(lái)回的set-cookie值加滲透到當前請求頭的cookie中以保持驗證碼請求與當前請求的一致性,然后再一并將新的密碼和用戶(hù)名Post到QQ的服務(wù)器上去。
好了,看了上面的QQ校驗方式以后,我們再來(lái)觀(guān)看怎樣使用代碼來(lái)登錄QQ空間及郵箱來(lái)獲取我們需要的好友和聯(lián)系人。
QQ空間及郵箱自動(dòng)登錄獲取聯(lián)系人的解決方案:
QQ空間及郵箱登陸首先我們需要將用戶(hù)輸入的密碼進(jìn)行Js加密,但是我們在使用代碼登錄的時(shí)候我們并沒(méi)有使用到瀏覽器。
那我們怎樣驅動(dòng)Js呢?不用怕,在Java和.NET中都有相應的方式在服務(wù)器代碼端驅動(dòng)JS,這里著(zhù)重講一下.NET的方法:
首先到微軟的網(wǎng)站上下載Windows Script Control。
它是一個(gè)ActiveX(R) 控件。下載安裝完成后。
新建一個(gè)C#應用程序項目,在解決方案資源管理器中選中引用節點(diǎn), 右鍵點(diǎn)擊選擇添加引用菜單。
彈出添加引用對話(huà)框,單擊瀏覽找到安裝Windows Script Control的目錄。
選取msscript.ocx文件確定。那么在引用節點(diǎn)下會(huì )增加一個(gè)MSScriptControl組件,下面是他Interop 后的所有對象。
<!--[if !vml]--><!--[endif]-->
ScriptControl 對支持 ActiveX(TM) Script 的宿主 Script 引擎提供簡(jiǎn)單接口。接下來(lái)我們對被轉化成ScriptControlClass類(lèi)的ScriptControl的屬性和方法進(jìn)行一些說(shuō)明。
屬性
AllowUI 屬性:應用于 ScriptControl 本身或 Scirpt 引擎顯示的用戶(hù)界面元素,可讀寫(xiě)。
CodeObject 屬性:返回對象,該對象用于調用指定模塊的公用成員。只讀。
Error 屬性:返回 Error 對象,其中包含所發(fā)生的最后一個(gè)錯誤的相關(guān)詳細信息。只讀。
Language 屬性:設置或返回正在使用的 Script 語(yǔ)言名稱(chēng)??勺x寫(xiě)。
Modules 屬性:為 ScriptControl 對象返回模塊集合。只讀。
Procedures 屬性:返回在指定模塊中定義的過(guò)程集合。只讀。
SitehWnd 屬性:設置或返回窗口的 hWnd。
通過(guò)執行 Script 代碼。
此窗口用于顯示對話(huà)框和其他用戶(hù)界面元素??勺x寫(xiě)。
State 屬性:設置或返往返 ScriptControl 對象的模式??勺x寫(xiě)。
Timeout 屬性:設置或返回時(shí)間(毫秒)。
此時(shí)間后用戶(hù)可選擇中止 Script 代碼的執行或允許代碼繼續執行??勺x寫(xiě)。
UseSafeSubset 屬性:設置或返回 Boolean 值,指明宿主應用程序是否有保密性要求。如果宿主應用程序需要安全控制。
則 UseSafeSubset 為 True,否則為 False??勺x寫(xiě)。
方法
AddCode 方法:向模塊添加指定代碼??啥啻握{用 AddCode 方法。
AddObject 方法:使主機對象模型對 Script 引擎可用。
Eval 方法:計算表達式并返來(lái)回結果。
ExecuteStatement 方法:執行指定的語(yǔ)句。
Reset 方法:放棄所有已經(jīng)添加到 ScriptControl 中的 Script 代碼和對象。
Run 方法:運行指定過(guò)程。
事件
Error 事件:出現運行時(shí)錯誤時(shí)。
發(fā)生此事件。
Timeout 事件:當超出了 Timeout 屬性指定的時(shí)間且用戶(hù)在結果對話(huà)框中選定了 End 時(shí)。
發(fā)生此事件。
說(shuō)明:
AllowUI 屬性如果設置為false。
則顯示對話(huà)框之類(lèi)的語(yǔ)句不起作用,如在 VBScript 中MsgBox 語(yǔ)句,JavaScript中的alert等,并且如果執行的腳本超出TimeOut設置的毫秒數。
也不會(huì )跳出超出時(shí)間提醒的對話(huà)框,反之則相反;重新設置 Language 屬性會(huì )清空AddCode加載的代碼;對于TimeOut屬性。
發(fā)生超時(shí)時(shí)。
ScriptControl 檢查對象的 AllowUI 屬性。
確定是否允許顯示用戶(hù)界面元素。
為了使控件更容易使用。
用ScriptEngine類(lèi)封裝一下。
下面是完整代碼:
using System;
using MSScriptControl;
using System.Text;
namespace ScriptNameSpace
{
///
/// 腳本類(lèi)型
///
public enum ScriptLanguage
{
///
/// JScript腳本語(yǔ)言
///
JScript,
///
/// VBscript腳本語(yǔ)言
///
VBscript,
///
/// JavaScript腳本語(yǔ)言
///
JavaScript
}
///
/// 腳本運行錯誤代理
///
public delegate void RunErrorHandler();
///
/// 腳本運行超時(shí)代理
///
public delegate void RunTimeoutHandler();
///
/// ScriptEngine類(lèi)
///
public class ScriptEngine
{
private ScriptControl msc;
//定義腳本運行錯誤事件
public event RunErrorHandler RunError;
//定義腳本運行超時(shí)事件
public event RunTimeoutHandler RunTimeout;
///
///構造函數
///
public ScriptEngine()
: this(ScriptLanguage.VBscript)
{ }
///
/// 構造函數
///
///腳本類(lèi)型
public ScriptEngine(ScriptLanguage language)
{
this.msc = new ScriptControlClass();
this.msc.UseSafeSubset = true;
this.msc.Language = language.ToString();
((DScriptControlSource_Event)this.msc).Error += new DScriptControlSource_ErrorEventHandler(ScriptEngin e_Error);
((DScriptControlSource_Event)this.msc).Timeout += new DScriptControlSource_TimeoutEventHandler(ScriptEng ine_Timeout);
}
///
/// 運行Eval方法
///
///表達式
///函數體
///
public object Eval(string expression, string codeBody)
{
msc.AddCode(codeBody);
return msc.Eval(expression);
}
///
/// 運行Eval方法
///
///腳本語(yǔ)言
///表達式
///函數體
///
public object Eval(ScriptLanguage language, string expression, string codeBody)
{
if (this.Language != language)
this.Language = language;
return Eval(expression, codeBody);
}
///
/// 運行Run方法
///
///滲透口函數名稱(chēng)
///參數
///函數體
///
public object Run(string mainFunctionName, object[] parameters, string codeBody)
{
this.msc.AddCode(codeBody);
return msc.Run(mainFunctionName, ref parameters);
}
///
/// 運行Run方法
///
///腳本語(yǔ)言
///滲入滲出口函數名稱(chēng)
///參數
///函數體
///
public object Run(ScriptLanguage language, string mainFunctionName, object[] parameters, string codeBody)
{
if (this.Language != language)
this.Language = language;
return Run(mainFunctionName, parameters, codeBody);
}
///
/// 放棄所有已經(jīng)添加到 ScriptControl 中的 Script 代碼和對象
///
public void Reset()
{
this.msc.Reset();
}
///
/// 獲取或設置腳本語(yǔ)言
///
public ScriptLanguage Language
{
get { return (ScriptLanguage)Enum.Parse(typeof(ScriptLanguage), this.msc.Language, false); }
set { this.msc.Language = value.ToString(); }
}
///
/// 獲取或設置腳本執行時(shí)間。
單位為毫秒
///
public int Timeout
{
get { return 0; }
}
///
/// 設置是否顯示用戶(hù)界面元素
///
public bool AllowUI
{
get { return this.msc.AllowUI; }
set { this.msc.AllowUI = value; }
}
///
/// 宿主應用程序是否有保密性要求
///
public bool UseSafeSubset
{
get { return this.msc.UseSafeSubset; }
set { this.msc.UseSafeSubset = true; }
}
///
/// RunError事件激發(fā)
///
private void OnError()
{
if (RunError != null)
RunError();
}
///
/// OnTimeout事件激發(fā)
///
private void OnTimeout()
{
if (RunTimeout != null)
RunTimeout();
}
private void ScriptEngine_Error()
{
OnError();
}
private void ScriptEngine_Timeout()
{
OnTimeout();
}
}
}
在找到.NET驅動(dòng)JS的方法以后,那么我們還需要找到QQ用來(lái)加密的那個(gè)JS文件,具體的JS文件大家可以到QQ的登錄頁(yè)面去DownLoad。
如果不知道是哪一個(gè)JS大家可以通過(guò)抓包的方式去找到。
這里就不再贅述了。下面我們就可以用MSScriptControl來(lái)驅動(dòng)JS獲取第一次加密的密碼了。
方法如下:
///
/// 得到第一次加密后的密碼
///
///js文件
///加密的方法名
///加密方法需要傳進(jìn)的參數(一個(gè)是密碼,另一個(gè)是頁(yè)面上可獲取的一個(gè)標志碼)
///
private object GetPassword(string jsFilePath, string funcName, params object[] paramers)
{
StreamReader reader = new StreamReader(jsFilePath);
string sScript = reader.ReadToEnd();
ScriptEngine se = new ScriptEngine(ScriptLanguage.JavaScript);
object obj = se.Run(funcName, paramers, sScript);
return obj;
}
通過(guò)上面的這個(gè)函數我們就可以對密碼進(jìn)行第一次加密了,下一步我們需要獲取驗證碼。
我們可以使用HttpWebRequest類(lèi)來(lái)Get請求這個(gè)地址:http://ptlogin2.qq.com/getimage來(lái)獲取驗證碼,不過(guò)一定要記住把這次請求返往返的cookie保存下來(lái)。
我們可以將它保存到CookieContainer對象中,以便將這次返回的cookie加滲入滲出到登錄POST請求的頭當中保持前后請求的一致性。
現在我們將獲得的驗證碼轉化成流或者其他的方式供不同的平臺輸出。
我們發(fā)現QQ空間及郵箱的驗證碼生成的圖像不是太復雜。
所以可以考慮使用圖像識別的方式自動(dòng)的獲取圖像對應的字符(現在有很多第三方驗證碼識別軟件)。
當然為了成功率考慮。
最好還是讓用戶(hù)手動(dòng)的輸入。
好了有了驗證碼了。
我們現在就將驗證碼字符加上剛剛我們加過(guò)密的密碼形成新字串。
再通過(guò)MD5加密
string pwd=FormsAuthentication.HashPasswordForStoringInCo nfigFile(this.Password, "MD5").ToLower()
形成最終我們需要的密碼。
最后我們就可以將用戶(hù)輸滲透的用戶(hù)名、密碼一并POST到QQ相應的地址上去,這樣我們就成功登陸QQ空間或郵箱了。登錄成功過(guò)后你當然就可以獲取聯(lián)系人好友等等的操作了。
好了。
文章就寫(xiě)到這了,希望對大家有用。^^ Brave chen
聯(lián)系客服