在之前的一篇博客里(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烦恼许多。
好了页面如下所示:
测试用户名和密码:jimmy_cmd@sina.com,密码123abc,拜托读者别干坏事改我密码。自己申请即可。
打开Fidder抓包工具,然后点击登录。
抓包工具分析内容如下:
对照的文本如下:
POST http://mail.sina.com.cn/cgi-bin/login.php HTTP/1.1
Accept: text/html, application/xhtml+xml, */*Referer: http://mail.sina.com.cn/cgi-bin/login.php
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MAAU)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: mail.sina.com.cn
Content-Length: 76
Connection: Keep-Alive
Pragma: no-cache
Cookie: freeName=w_wangj_jian@sina.com; SINAMAIL-WEBFACE-SESSID=f4762bf7601ac04e5c03a344f5160a59; UOR=,,; U_TRS1=000000b4.2d6a4a30.4dbeccdf.f7085a45; vjuids=-8a3c2a43b.12f673b30db.0.8ab6cd7a91ca3; vjlast=1304434711; SINAGLOBAL=00000049.c6df3442.4e8ecea8.c10d0d3d; ULV=1320734979210:14:4:4:00000042.bb0b52da.4eb8d102.c45af59b:1320732064442; ALLYESID4=00110503104143503706036; SGUP=0; FocusMediaIpCgiCookie=%u6C5F%u82CF%7C%7C%u5357%u4EAC; FocusMediaRotatorInputCookie=9; FocusMediaRotatorCookie=3; mvsign=v%3D%2Atz%3Cc5uhs4CE5F_%24Uf5%3E; loginType=freemail; SHOW_TIP_BOX=1; Apache=00000042.bb0b52da.4eb8d102.c45af59b; _s_upa=7; ULOGIN_IMG=13207484207872; U_TRS2=000000a2.96d8223d.4eb8dfc0.1bfdd2e1; SID=BVmfqfgs-93K99ffg3qrKL3f97qLf-3fKqfKqkqfgfqapWkm3L9RK9q; SPRIAL=d38fb34629f58bca2d47db89f8bcc1f5; SINA_USER=jimmy_cmd
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);
- }
对WinInet API的理解,可以去 http://msdn.microsoft.com/zh-cn/default.aspx 搜索查看。
忘了贴结果了!双击接收到的文件,如下所示,可以看出来是想要的结果~