在之前的一篇博客里(http://blog.csdn.net/wangjiannuaa/article/details/6689906)分析了如何使用了C#登录网页。有的人如果密码就是纯数字,那么用这种方法就可以暴力简单得破解了。不过笔者前几天发现,用于实验的人人网登录需要了验证码,用户是觉得烦了,诸不知这也算是保护措施吧。
第一次使用WinInet编程是去年,用于抓取网页的股票数据(http://blog.csdn.net/wangjiannuaa/article/details/5959375),最近搜索这方面知识的时候再网上找到了新浪邮箱的自动登录程序,那么就以此展开,演示如何使用WinInet 登录web。原文地址:http://www.cctry.com/thread-1181-1-1.html。
经过分析,文章中的表单地址并非正统的 http://mail.sina.com.cn/ 而是 http://mail.sina.com.cn/cgi-bin/login.php 如下图所示。这样做的好处个人认为是规避了安全性的障碍,没有多少js,各种花哨,没有验证码……
我相信作者尝试过http://mail.sina.com.cn/,比http://mail.sina.com.cn/cgi-bin/login.php烦恼许多。
好了页面如下所示:
测试用户名和密码:[email protected],密码123abc,拜托读者别干坏事改我密码。自己申请即可。
打开Fidder抓包工具,然后点击登录。
抓包工具分析内容如下:
对照的文本如下:
POST http://mail.sina.com.cn/cgi-bin/login.php HTTP/1.1
Accept: text/html, application/xhtml+xml, */*logintype=uid&u=jimmy_cmd&psw=123abc&product=mail&%B5%C7%C2%BC=%B5%C7+%C2%BC
InternetOpen->InternetConnect->HttpOpenRequest->HttpSendRequest系统中顺序调用上面这四个WinInet API完成一次Http请求.
下面,对照以上红色字体的说明,代码改写如下:
#include<windows.h> #include<wininet.h> #pragma comment(lib,"wininet.lib") void main() { HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; //InternetOpenA LPCSTR lpszAgent = "Application"; DWORD dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG; hSession = InternetOpenA(lpszAgent,dwAccessType,NULL,NULL,0); if (!hSession) { return ; } //InternetConnectA LPCSTR lpszServerName = "mail.sina.com.cn"; INTERNET_PORT nServerPort = INTERNET_DEFAULT_HTTP_PORT; DWORD dwService = INTERNET_SERVICE_HTTP; hConnect = InternetConnectA(hSession,lpszServerName,nServerPort,NULL,NULL,dwService,0,1); if (!hConnect) { return ; } //HttpOpenRequestA LPCSTR lpszVerb = "POST"; LPCSTR lpszObjectName = "cgi-bin/login.php"; //网站的对象名,网址在InternetConnectA第二个参数指定 LPCSTR lpszVersion = "HTTP/1.1"; LPCSTR lpszReferrer = "Referer: http://mail.sina.com.cn/cgi-bin/login.php"; LPCSTR lpszAcceptTypes = "Accept: text/html, application/xhtml+xml, */*"; DWORD dwFlags = INTERNET_FLAG_RELOAD; hRequest = HttpOpenRequestA(hConnect,lpszVerb,lpszObjectName,lpszVersion,lpszReferrer,&lpszAcceptTypes,dwFlags,1); if (!hRequest) { return; } //HttpSendRequestA LPCSTR lpszHeaders = "Content-Type: application/x-www-form-urlencoded\r\n"; DWORD dwHeadersLength=-1L; char szFormData[1024]={0}; strcpy(szFormData,"logintype=uid&u=jimmy_cmd&psw=123abc&product=mail&%B5%C7%C2%BC=%B5%C7+%C2%BC\r\n"); LPVOID pBuf = (LPVOID)szFormData; BOOL bReturn = HttpSendRequestA(hRequest,lpszHeaders,dwHeadersLength,pBuf,strlen(szFormData)); if(!bReturn) { return; } char szRecvBuf[1024+1]; // 接受数据缓冲区 DWORD dwNumberOfBytesRead; // 服务器返回大小 DWORD dwRecvTotalSize=0; // 接受数据总大小 DWORD dwRecvBuffSize=0; // 接受数据buf的大小 memset(szRecvBuf,0,1024+1); LPCSTR lpFileName = "recv.html"; DWORD dwNumberOfBytesWritten ; HANDLE hOpenFile = (HANDLE)CreateFileA(lpFileName,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,NULL,NULL); if (hOpenFile == INVALID_HANDLE_VALUE) { hOpenFile = NULL; return ; } do { bReturn = InternetReadFile(hRequest,szRecvBuf,1024,&dwNumberOfBytesRead); if(!bReturn) { break; } // 统计接受数据的大小 szRecvBuf[dwNumberOfBytesRead] = '\0'; dwRecvTotalSize += dwNumberOfBytesRead; dwRecvBuffSize += strlen(szRecvBuf); WriteFile(hOpenFile,szRecvBuf,dwNumberOfBytesRead,&dwNumberOfBytesWritten,NULL); } while (dwNumberOfBytesRead !=0); CloseHandle(hOpenFile); InternetCloseHandle(hSession); InternetCloseHandle(hConnect); InternetCloseHandle(hRequest); }
忘了贴结果了!双击接收到的文件,如下所示,可以看出来是想要的结果~