用程式登入Aps.Net頁面
來源:互聯網
上載者:User
程式|頁面 在寫Internet應用程式的時候,常常需要處理使用者登入的情況。一般來說,對於這種情況,我們是使用程式來類比使用者在Web頁面上填寫使用者名稱、密碼並提交的過程。當使用者在Web頁面上輸入了使用者名稱、密碼並提交之後,實際上是觸發了一個POST請求,在這個請求中包含有使用者名稱、密碼等資訊。因此,我們只要在程式中將相關資訊封裝成一條POST請求,並將它發送給Web Server,基本上就能實現登入了。以MFC為例,下面的這段代碼類比了一個登入過程:
CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded");
// name = "sam", password = "123", action = "submit"
CString strFormData = _T("name=sam&password=123&action=submit");
CInternetSession session;
CHttpConnection* pConnection =
session.GetHttpConnection(_T("ServerNameHere"));
CHttpFile* pFile =
pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,
_T("FormActionHere"));
BOOL result = pFile->SendRequest(strHeaders,
(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());
這個方法對於Asp頁面很有效,但對於Asp.Net頁面,有時卻不起作用,這是為什麼呢?
為了搞清出Asp.Net頁面在處理登入時與Asp頁面有何區別,我們需要使用Sniffer工具來跟蹤Web伺服器與瀏覽器之間的通訊。經過跟蹤會發現,Asp.Net頁面在使用者提交登入資訊之後,仍然是使用POST請求將相關資訊發送給伺服器。所不同的是,處理使用者名稱、密碼等資訊之外還多了一個__VIEWSTATE。如果在上面代碼中的strFormData中加上一個通過Sniffer得到的__VIEWSTATE的話,就能夠成功類比出整個登入過程了。接下來的問題就是,我們應該如何獲得這個__VIEWSTATE呢?
我們知道,Asp.Net頁面有一個ViewState屬性,Asp.Net用它來儲存頁面的狀態資訊,以便在頁面提交失敗時,能夠恢複頁面的狀態。它是通過頁面中的一個隱藏的域來定義的,如果通過瀏覽器來View Source的話,可以看到它是如下的一行代碼
它的value值正是我們所需要的,我們只要從登入頁面中解析出這個__VIEWSTATE的value,我們的問題就能夠得到解決了。
仔細看一下,ViewState的值是經過編碼的,先不管它,直接將它從頁面中取出,和登入資訊一起組成POST請求,發送給Server,結果如何呢?失敗了L。對比一下Sniffer的結果和頁面中ViewState的value,我們會發現,它們之間還是有些許不同的。原來,頁面源碼中的ViewState值是經過Base64編碼的,而當它被發送給Web Server時,為了保證傳輸的正確,瀏覽器會將它轉換成URL編碼,當Web Server接收到ViewState之後,當然會先將它從URL編碼解碼為Base64編碼再交給Asp.Net處理。看來我們需要將ViewState的值在進行一邊URL編碼處理,這樣就能夠成功類比整個登入過程了J。
參考
1. HOWTO: Simulate a Form POST Request Using WinInet,微軟的KB文章,描述了類比POST請求的實現。
2. ASP .NET Maintaining the ViewState,ViewState的入門知識。
3. ViewState: All You Wanted to Know,關於ViewState的深入討論。
4. ViewState Parser,想看看解碼後的ViewState是什麼樣子嗎?試試這個Parser。
5. 部落格堂中的相關討論,這是我在解決這個問題的過程中,在部落格堂寫的Blog。