WinInet初识: 登录web

在之前的一篇博客里(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,各种花哨,没有验证码……

WinInet初识: 登录web_第1张图片

我相信作者尝试过http://mail.sina.com.cn/,比http://mail.sina.com.cn/cgi-bin/login.php烦恼许多。

好了页面如下所示:

WinInet初识: 登录web_第2张图片

测试用户名和密码:[email protected],密码123abc,拜托读者别干坏事改我密码。自己申请即可。

打开Fidder抓包工具,然后点击登录。

抓包工具分析内容如下:

WinInet初识: 登录web_第3张图片

对照的文本如下:

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: [email protected]; 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 搜索查看。


忘了贴结果了!双击接收到的文件,如下所示,可以看出来是想要的结果~

WinInet初识: 登录web_第4张图片


你可能感兴趣的:(WinInet初识: 登录web)