C ++ simulates Http/Https POST to log on to the web site

Source: Internet
Author: User

C ++ simulates Http/Https POST to log on to the web site
C ++ simulates Http/Https access to web sites 1. Overview 1. Differences and connection between Http and Https

In the OSI reference model, both Http and Https belong to the application layer protocol. Http is Hypertext Transfer Protocol, Hypertext Transfer Protocol; Https Is Secure Hypertext Transfer Protocol, which is a Secure communication channel developed based on HTTP, it is used to exchange information between the client and the server. It uses Secure Socket Layer SSL for information exchange. In short, it is the secure version of HTTP.

Http uses port 80 by default and Https uses port 443.

Http data is transmitted in plain text on the network, while Https is transmitted through encrypted transmission. Therefore, it is more secure than http. However, due to the need for additional encryption and decryption operations, because Https is less efficient. When logging on to an Https site or an Http site, you can clearly feel the performance difference.

2. web Access Security

At present, many web sites use common http for transmission during login, which poses a great security risk. Currently, the following four methods are commonly used to log on to the web development system:

1) The account and password are completely unencrypted and transmitted in plaintext. The security level of this method is the lowest. It undoubtedly exposes its account and password to others and uses the packet capture tool (for example, WireShark) you can easily intercept accounts and passwords.

2) The password is encrypted using MD5 or other encryption methods and cannot be cracked. In fact, there is no need to crack it. As long as you intercept the encrypted password string, you can access the server as your identity, which can also pass authentication and authorization. This method is encrypted to a certain extent, but it is still insecure.

3) The client obtains the key once before logging on to the server and encrypts it. The key on the server is randomly generated and different keys are used for each access. This method is highly secure.

4) the "most secure" HTTPS mode is used for transmission. The client and server are authenticated and all intermediate transmission data is encrypted. It is not absolutely safe to add quotation marks to the highest security level. For example, some time ago, Openssl revealed a security vulnerability, and the famous "heartbleed" was exploited by hackers to exploit its memcpy bug, you can obtain 64 KB of user data from the overflow memory, resulting in user information leakage. However, this security level is the highest than the first three. The current server certificate charges about 3-5 thousand a year. It is very cost-effective to use this money for relative security.

Ii. Basic Process for sending HTTP requests through SOCKET

Both Http and Https are transmitted over TCP. Therefore, it is very easy to use SOCKET to simulate HTTP access to the web site, that is, to splice the header data into a data packet and send it to the server, then you can receive the response and parse it.

The basic process is the same as writing common SOCKET communication. In Windows, the process is as follows:

A. WSAStartup initializes the Winsock Service

B. Establish socket

C. connect to the server

D. send data

E. recv receives data

In the following example, the POST header information captured by Fiddler is as follows:

In this way, we can build such a data packet to send and receive the response. For the C ++ implementation core code, see the following section.

2. Core code
BOOL SocketClient: ConnectToServer (const CString strServerUrl, const int nPort) {cstrServerUrl = strServerUrl; nServerPort = nPort; BOOL bRet = FALSE; do {if (! InitializeContext () {break;} if (! Connect () {break;} bRet = TRUE;} while (FALSE); return bRet;} BOOL SocketClient: logtailserver (const CString strUsername, const CString strPasswd) {cstrUserName = strUsername; cstrPassWord = strPasswd; BOOL bRet = FALSE; do {if (! SendPostData () {break;} bRet = TRUE;} while (FALSE); return bRet;} BOOL SocketClient: LogoutOfServer () {return FALSE;} BOOL SocketClient :: initializeContext () {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) {response (); break;} LPHOSTENT lpHostTent; lpHostTent = gethostbyname (cstrServerUrl); if (NULL = lpHostTent) {break;} socketClient = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (socketClient = protocol) {protocol (); break;} socketAddrClient = new protocol; socketAddrClient-> sin_family = AF_INET; socketAddrClient-> sin_port = htons (nServerPort ); socketAddrClient-> sin_addr = * (LPIN_ADDR) * lpH OstTent-> h_addr_list); memset (socketAddrClient-> sin_zero, 0, sizeof (socketAddrClient-> sin_zero); bRet = TRUE;} while (FALSE); return bRet ;} BOOL SocketClient: Connect () {BOOL bRet = FALSE; do {if (SOCKET_ERROR = connect (socketClient, (LPSOCKADDR) socketAddrClient, sizeof (SOCKADDR_IN ))) {int nErrorCode = WSAGetLastError (); closesocket (socketClient); break;} bRet = TRUE ;}while (FALSE); return bRet;} BOOL Soc KetClient: SendPostData () {CString cstrSendData; CString cstrSendParam = redirect = & username = + cstrUserName + & password = + cstrPassWord + & auto_login = checked & submit = % E7 % 99% BB % E5 % BD % 95; BOOL bRet = FALSE; CString cstrSendParamLen; cstrSendParamLen. format (% d, cstrSendParam. getLength (); cstrSendData = POST http://account.vsochina.com/user/login HTTP/1.1; cstrSendData + = Host: account.vsochina.com; cstrSendData + = U Ser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv: 35.0) Gecko/20100101 Firefox/35.0; cstrSendData + = Accept: text/html, application/xhtml + xml, application/xml; q = 0.9, */*; q = 0.8; cstrSendData + = Accept-Language: zh-cn, zh; q = 0.8, en-us; q = 0.5, en; q = 0.3; cstrSendData + = Accept-Encoding: gzip, deflate; cstrSendData + = DNT: 1; cstrSendData + = Referer: http://account.vsochina.com/user/login;cstrSendData + = Connectio N: keep-alive; cstrSendData + = Content-Type: application/x-www-form-urlencoded; cstrSendData + = Content-Length: + cstrSendParamLen +; cstrSendData + =; cstrSendData + = cstrSendParam; CString cstrRecvData; do {if (-1 = send (socketClient, cstrSendData. getBuffer (), cstrSendData. getLength (), 0) {break;} char recvData [1000] = {0}; int nRecvLen; while (nRecvLen = recv (socketClient, recvData, sizeof (recvData ), 0 )> 0) {cstrRecvData + = recvData;} if (cstrRecvData. GetLength () = 0) {break;} ParseCookieFromRecvData (cstrRecvData );//! Determine whether the returned COOKIE information contains the UID if (cstrCookieUid. isEmpty () {break;} bRet = TRUE;} while (FALSE); return bRet;} void SocketClient: ParseCookieFromRecvData (const CString cstrRecvData) {list
 
  
LstCookiesLine ;//! A row storing the Set-Cookie, for example, Set-Cookie: vso_uname = houqd_1111; CString cstrFind = Set-Cookie :;//! Search mark CString cstrSeperator = ;//! Split the string int nPos = 0 by number. int nStart = cstrRecvData. Find (cstrSeperator); while (nStart! =-1) {CString cstrSessionLine = cstrRecvData. Mid (nPos, nStart-nPos + 1); if (cstrSessionLine. Find (cstrFind )! =-1) {CString cstrRealRecord = cstrSessionLine. Right (cstrSessionLine. GetLength ()-cstrFind. GetLength ()-3); list
  
   
: Iterator it = find (lstCookiesLine. begin (), lstCookiesLine. end (), cstrRealRecord); if (it = lstCookiesLine. end () {lstCookiesLine. push_back (cstrRealRecord) ;}} nPos = nStart; nStart = cstrRecvData. find (cstrSeperator, nPos + 2 );}//! The cookie value obtained by each row is parsed into a key-value form vector.
   
    
VecCookieSet; for (list
    
     
: Iterator it = lstCookiesLine. begin (); it! = LstCookiesLine. end (); it ++) {CString cstrCookies = * it; CString cstrSeperator =; StaticUtility: StringSplit (cstrCookies, cstrSeperator, vecCookieSet);} vector
     
      
VecTemp; for (vector
      
        : Iterator it = vecCookieSet. begin (); it! = VecCookieSet. end (); it ++) {vecTemp. clear (); CString cstrOneCookies = * it; CString cstrSeperator =; StaticUtility: StringSplit (cstrOneCookies, cstrSeperator, vecTemp); CString cstrKey = vecTemp [0]; CString cstrVal = vecTemp [1]; if (cstrKey. compare (vso_uid) = 0) {cstrCookieUid = cstrVal; break ;}}}
      
     
    
   
  
 

By parsing the cookie information in the Received Header information, you can determine whether the logon is successful. Then, if you have any possible operations, you can get the desired data and complete the desired operations by attaching the cookie information to the request.

3. Sending HTTPS requests through OpenSSL 1. Basic Process

HTTPS = HTTP + SSL. Therefore, the use of OpenSSL to send requests to the HTTPS site is very similar to the SOCKET in Chapter 2, except that the SSL layer must be mounted on the native SOCKET, the basic process is as follows:

A. WSAStartup initializes the Winsock Service

B. Establish socket

C. connect to the server

D. Create an SSL Context

E. Establish SSL

F. Bind SSL to the socket established earlier

G. SSL_write () sends data

H. SSL_read () receives data

The following describes how to use OpenSSL to access the HTTPS site, simulate logon, and use the core code. For more information, see the next section.

2. Core code
# 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 ){//! Clear the opened handle 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: logtailserver (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 (){//! Initialize the winSocket environment 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) {response (); break;} LPHOSTENT lpHostTent; lpHostTent = gethostbyname (cstrServerUrl); if (NULL = lpHostTent) {break;} socketClient = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (socketClient = protocol) {protocol (); break;} socketAddrClient = new protocol; socketAddrClient-> sin_family = AF_INET; socketAddrClient-> sin_port = htons (nServerPort ); socketAddrClient-> sin_addr = * (LPIN_ADDR) * lpH OstTent-> h_addr_list); memset (socketAddrClient-> sin_zero, 0, sizeof (socketAddrClient-> sin_zero); bRet = TRUE;} while (FALSE); return bRet ;} BOOL HttpsClient: SocketConnect (){//! Native socket connection BOOL bRet = FALSE; do {if (SOCKET_ERROR = connect (socketClient, (LPSOCKADDR) socketAddrClient, sizeof (SOCKADDR_IN) {int nErrorCode = WSAGetLastError (); closesocket (socketClient); break;} bRet = TRUE;} while (FALSE); return bRet;} BOOL HttpsClient: InitializeSslContext (){//! SSL communication initialization BOOL bRet = FALSE; do {sslMethod = SSLv23_client_method (); if (NULL = sslMethod) {break;} sslCtx = SSL_CTX_new (sslMethod ); if (NULL = sslCtx) {break;} ssl = SSL_new (sslCtx); if (NULL = ssl) {break;} bRet = TRUE;} while (FALSE ); return bRet;} BOOL HttpsClient: SslConnect (){//! SSL binds native socket and connects to the server BOOL bRet = FALSE; do {SSL_set_fd (ssl, socketClient); int nRet = SSL_connect (ssl); if (-1 = nRet) {break;} bRet = TRUE;} while (FALSE); return bRet;} BOOL HttpsClient: SslGetCipherAndCertification () {BOOL bRet = FALSE; do {cstrSslCipher = SSL_get_cipher (ssl ); serverCertification = SSL_get_certificate (ssl); if (NULL = serverCertification) {break;} cstrSslSubject = X509_NAME_oneline (X509_get _ Subject_name (serverCertification), 0, 0); cstrSslIssuer = X509_NAME_oneline (certificate (serverCertification), 0, 0); X509_free (serverCertification); bRet = TRUE;} while (FALSE ); return bRet;} BOOL HttpsClient: SendLoginPostData () {CString cstrSendData; // CString cstrSendParam = redirect = & username = + cstrUserName + & password = + cstrPassWord + & auto_login = checked & submit = % E7 % 99% BB % E5 % BD % 95; CString cstrSen DParam = user = + cstrUserName + & _ json = true & pwd = + cstrPassWord + & callback = http % 3A % 2F % 2Forder.mi.com % 2 Flogin % 2 Fcallback % 3 Ffollowup % 3 Dhttp % 253A % 252F % 252Fwww.mi.com % 252F % 26 sign % %2c % 2C & sid = mi_eshop & qs = % 253 Fcallback % 253 Dhttp % 25253A % 25252F % 25252Forder.mi.com % 25252 Flogin % 25252 Fcallback % 25253 Ffollowup % 25253 Dhttp % 25253a % 25252f % 2525252Fwww.mi.com % 2525252 F % 252526 sign % signature % 25252C % 25252C % 2526sid % 253Dmi_eshop & hidden = & _ sign = % signature % 2BF0QG4jE % 3D & serviceParam = % 7B % 22 checkSafePhone % 22% 3 Afalse % 7D & captCode =; BOOL bRet = FALSE; CString cstrSendParamLen; cstrSendParamLen. format (% d, cstrSendParam. getLength (); cstrSendData = POST https://account.xiaomi.com/pass/serviceLoginAuth2 HTTP/1.1; cstrSen DData + = Host: account.xiaomi.com; cstrSendData + = User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv: 35.0) Gecko/20100101 Firefox/35.0; cstrSendData + = Accept: text/html, application/xhtml + xml, application/xml; q = 0.9, */*; q = 0.8; cstrSendData + = Accept-Language: zh-cn, zh; q = 0.8, en-us; q = 0.5, en; q = 0.3; cstrSendData + = Accept-Encoding: gzip, deflate; cstrSendData + = DNT: 1; cstrSendData + = Content-Type: applicat Ion/x-www-form-urlencoded; charset = UTF-8; cstrSendData + = Referer: https://account.xiaomi.com/pass/serviceLogin? Percent % 26 sign % percent % 2C % 2C & sid = mi_eshop; cstrSendData + = Content-Length: + cstrSendParamLen +; cstrSendData + = Connection: keep-alive; cstrSendData + =; cstrSendData + = cstrSendParam; CString cstrRecvData; do {int nRet = SSL_write (ssl, cstrSendData, cs TrSendData. getLength (); if (-1 = nRet) {break;} bRet = TRUE;} while (FALSE); return bRet;} void HttpsClient :: recvLoginPostData (CString & cstrRecvData) {BOOL bRet = FALSE; do {TIMEVAL tval; tval. TV _sec = 20; tval. TV _usec = 0; while (TRUE) {FD_SET fds; FD_ZERO (& fds); FD_SET (socketClient, & fds); char recvData [1000] = {0}; int nRecvLen; // int nSelect = select (FD_SETSIZE, & fds, NULL, NULL, & tval); // if (1! = NSelect) // {// break; //} int nErr = SSL_read (ssl, recvData, sizeof (recvData); if (nErr <= 0) {break ;} cstrRecvData + = recvData;} if (cstrRecvData. getLength () = 0) {break;} bRet = TRUE;} while (FALSE);} void HttpsClient: ParseCookieFromRecvData (const CString cstrRecvData) {list
 
  
LstCookiesLine ;//! A row storing the Set-Cookie, for example, Set-Cookie: vso_uname = houqd_1111; CString cstrFind = Set-Cookie :;//! Search mark CString cstrSeperator = ;//! Split the string int nPos = 0 by number. int nStart = cstrRecvData. Find (cstrSeperator); while (nStart! =-1) {CString cstrSessionLine = cstrRecvData. Mid (nPos, nStart-nPos + 1); if (cstrSessionLine. Find (cstrFind )! =-1) {CString cstrRealRecord = cstrSessionLine. Right (cstrSessionLine. GetLength ()-cstrFind. GetLength ()-3); list
  
   
: Iterator it = find (lstCookiesLine. begin (), lstCookiesLine. end (), cstrRealRecord); if (it = lstCookiesLine. end () {lstCookiesLine. push_back (cstrRealRecord) ;}} nPos = nStart; nStart = cstrRecvData. find (cstrSeperator, nPos + 2 );}//! The cookie value obtained by each row is parsed into a key-value form vector.
   
    
VecCookieSet; for (list
    
     
: Iterator it = lstCookiesLine. begin (); it! = LstCookiesLine. end (); it ++) {CString cstrCookies = * it; CString cstrSeperator =; StaticUtility: StringSplit (cstrCookies, cstrSeperator, vecCookieSet);} vector
     
      
VecTemp; for (vector
      
        : Iterator it = vecCookieSet. begin (); it! = VecCookieSet. end (); it ++) {vecTemp. clear (); CString cstrOneCookies = * it; CString cstrSeperator =; StaticUtility: StringSplit (cstrOneCookies, cstrSeperator, vecTemp); CString cstrKey; CString cstrVal; if (vecTemp. size () = 2) {cstrKey = vecTemp [0]; cstrVal = vecTemp [1];} if (cstrKey. compare (userId) = 0) {cstrCookieUid = cstrVal; break ;}}}
      
     
    
   
  
 

Similarly, determining whether a logon is to take the cookie information in the returned information before proceeding to the next step.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.