C++模拟Http/Https POST登录web站点(四)

2015-07-20 17:08:16 · 作者: · 浏览: 19
ie信息,就可以获取想要的数据,完成想要的操作了。

三、OpenSSL发送HTTPS请求

1.基本流程

HTTPS=HTTP + SSL,因此利用OpenSSL发送请求给HTTPS站点和第二章的SOCKET发送HTTP是非常相似的,只不过要在原生的套接字上套上SSL层,基本流程如下:

a. WSAStartup对Winsock服务进行初始化

b. 建立socket套接字

c. connect连接服务端

d. 建立SSL上下文

e. 建立SSL

f. 将SSL与前面建立的socket套接字绑定

g. SSL_write()发送数据

h. SSL_read()接收数据

下面以小米官网站点的登录为例,来展示利用OpenSSL如何访问HTTPS站点,模拟登陆,核心代码,见下一章节。

2.核心代码

#pragma comment( lib, libeay32.lib )
#pragma comment( lib, ssleay32.lib )
HttpsClient::HttpsClient(void):
			 wsaData(NULL),
		     socketAddrClient(NULL),
			 ssl(NULL),
			 sslCtx(NULL),
			 sslMethod(NULL),
			 serverCertification(NULL)
{
	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();
}


HttpsClient::~HttpsClient(void)
{
	//!清理打开的句柄
	if (NULL != ssl)
	{
		SSL_shutdown(ssl);
		closesocket(socketClient);
		SSL_free(ssl);
		ssl = NULL;
	}

	if (NULL != sslCtx)
	{
		SSL_CTX_free(sslCtx);
	}

	WSACleanup();
}

BOOL HttpsClient::ConnectToServer(const CString strServerUrl, const int nPort)
{
	cstrServerUrl = strServerUrl;
	nServerPort = nPort;
	BOOL bRet = FALSE;

	do 
	{
		if (!InitializeSocketContext())
		{
			break;
		}

		if (!SocketConnect())
		{
			break;
		}

		if (!InitializeSslContext())
		{
			break;
		}

		if (!SslConnect())
		{
			break;
		}

		bRet = TRUE;
	} while (FALSE);
	return bRet;
}

BOOL HttpsClient::LoginToServer(const CString strUsername, const CString strPasswd)
{
	cstrUserName = strUsername;
	cstrPassWord = strPasswd;
	BOOL bRet = FALSE;

	do 
	{
		if (!SendLoginPostData())
		{
			break;
		}

		CString cstrRecvData;
		RecvLoginPostData(cstrRecvData);
		if (cstrRecvData.GetLength() == 0)
		{
			break;
		}

		ParseCookieFromRecvData(cstrRecvData);

		if (cstrCookieUid.IsEmpty() || cstrCookieUid.Compare(EXPIRED) == 0)
		{
			break;
		}

		bRet = TRUE;
	} while (FALSE);
	return bRet;
}

BOOL HttpsClient::LogoutOfServer()
{
	return FALSE;
}

BOOL HttpsClient::InitializeSocketContext()
{
	//!初始化winSocket环境
	BOOL bRet = FALSE;
	wsaData = new WSADATA;
	WORD wVersion = MAKEWORD(2, 2);

	do 
	{
		if(0 != WSAStartup(wVersion, wsaData))
		{
			break;
		}

		if(LOBYTE( wsaData->wVersion ) != 2 || HIBYTE( wsaData->wVersion ) != 2 )
		{
			WSACleanup();
			break;
		}

		LPHOSTENT lpHostTent;
		lpHostTent = gethostbyname(cstrServerUrl);
		if (NULL == lpHostTent)
		{
			break;
		}

		socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (socketClient == INVALID_SOCKET)
		{
			WSACleanup();
			break;
		}

		socketAddrClient = new SOCKADDR_IN;
		socketAddrClient->sin_family = AF_INET;
		socketAddrClient->sin_port = htons(nServerPort);
		socketAddrClient->sin_addr = *((LPIN_ADDR)*lpHostTent->h_addr_list);
		memset(socketAddrClient->sin_zero, 0, sizeof(socketAddrClient->sin_zero));

		bRet = TRUE;
	} while (FALSE);

	return bRet;
}

BOOL HttpsClient::SocketConnect()
{
	//!原生socket连接
	BOOL bRet = FALSE;

	do 
	{
		if (SOCKET_ERROR == connect(socketClient, (LPSOCKADDR)socketAddrClient, sizeof(SOCKADDR_IN)))
		{
			int nErrorCode = WSAGetLastError();
			closesocket(socketClient);