如何将HTML表单发送到网站进行登录,并以c ++下载网页(使用WinHTTP API)

时间:2014-10-23 15:54:12

标签: c++ webforms winhttp

  

您好!我正在尝试登录网站并下载授权   页。目前,该网站不需要任何身份验证   schema(我从响应头中找到了这个)。名称和密码是   只是通过PHP脚本验证(我想是这样)。登录页面是   “http://example.com/dashboard/index.php”。和我想要的页面   下载是“http://example.com/dashboard/dashboard.php”。 Chrome是   正常显示仪表板页面。但总是在cpp代码之下   在POST请求后甚至下载登录页面。那有什么不对   在里面?这个html代码是登录页面的表单。提前谢谢!

**************************************************************
<form name="login_form" action="" method="post" id="login_form"> 
                <div class="full mar2">
                    <div class="login-left">Username</div>
                    <div class="login-right">
                      <label>
                      <input type="text" name="username" value="" class="user"  />
                      </label>
                    </div>
                </div>
                <div class="full mar2">
                    <div class="login-left">Password</div>
                    <div class="login-right">
                      <label>
                      <input type="password" name="pswd" value="" class="user" />
                      </label>
                    </div>
                </div>
                <div class="full mar2">
                    <div class="login-left">&nbsp;</div>
                    <div class="login-right"><input type="submit" value="" name="sub_login" class="log-in" /></div>
                </div>
                <input type="hidden" name="sub_check" value="1" id="sub_check" />
                </form>
*******************************************************************



string GetHTMLTextFromWWW()
{
    HINTERNET hSess;
    hSess = WinHttpOpen(
        L"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36",
        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS,
        0);
    if (!hSess) return "";

    HINTERNET hConn;
    hConn = WinHttpConnect(
        hSess,
        L"www.example.com",
        INTERNET_DEFAULT_PORT,
        0);
    if (!hConn)
    {
        WinHttpCloseHandle(hSess);
        return "";
    }

    HINTERNET hReq;
    hReq = WinHttpOpenRequest(
        hConn,
        L"POST",
        L"/dashboard",
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_REFRESH);
    if (!hReq)
    {
        WinHttpCloseHandle(hConn);
        WinHttpCloseHandle(hSess);
        return "";
    }

    BOOL bRes;
    // I got the names from login page's html form
    char* data = "username=aan1982&pswd=admin1234&sub_check=1&sub_login=";
    WinHttpSendRequest(
        hReq,
        L"Content-Type: application/x-www-form-urlencoded\r\n",
        -1,
        (LPVOID)data,
        strlen(data),
        strlen(data),
        0);

    bRes = WinHttpReceiveResponse(hReq, NULL);
    if (!bRes)
    {
        WinHttpCloseHandle(hReq);
        WinHttpCloseHandle(hConn);
        WinHttpCloseHandle(hSess);
        return "";
    }
    WinHttpCloseHandle(hReq);
    //...
    hReq = WinHttpOpenRequest(
        hConn,
        L"GET",
        L"/dashboard/dashboard.php",
        NULL,
        L"http://example.com/dashboard/index.php",
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_REFRESH);
    if (!hReq)
    {
        WinHttpCloseHandle(hConn);
        WinHttpCloseHandle(hSess);
        return "";
    }

    WinHttpSendRequest(
        hReq,
        WINHTTP_NO_ADDITIONAL_HEADERS,
        0,
        WINHTTP_NO_REQUEST_DATA,
        0,
        0,
        0);

    bRes = WinHttpReceiveResponse(hReq, NULL);
    if (!bRes)
    {
        WinHttpCloseHandle(hReq);
        WinHttpCloseHandle(hConn);
        WinHttpCloseHandle(hSess);
        return "";
    }

    DWORD cbSize(0);
    DWORD cbDownloaded;
    string Text = "";
    char *Buffer;
    do
    {
        cbSize = 0;
        if (WinHttpQueryDataAvailable(hReq, &cbSize))
        {
            Buffer = new (nothrow) char[cbSize + 1];
            if (Buffer)
            {
                ZeroMemory(Buffer, cbSize + 1);
                if (WinHttpReadData(hReq, (LPVOID)Buffer, cbSize, &cbDownloaded))
                    Text += Buffer;
                delete [] Buffer;
            }
        }
    } while (cbSize > 0);

    WinHttpCloseHandle(hReq);
    WinHttpCloseHandle(hConn);
    WinHttpCloseHandle(hSess);
    return Text;
}

1 个答案:

答案 0 :(得分:0)

如果是简单的身份验证,您必须执行以下步骤:

  1. (由您完成)hSess = WinHttpOpen(..);
  2. (由您完成)hConn = WinHttpConnect(hSess, ..);
  3. hReq = WinHttpOpenRequest(hConn, L"GET", ..); // create get request
  4. 致电WinHttpSendRequest(hReq, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);告知HTTP服务器您的意图
  5. 致电WinHttpReceiveResponse(hReq, ..);
  6. 接收回复
  7. 查询请求的状态:WinHttpQueryHeaders(hReq, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, ..);
  8. 如果WinHttpQueryHeader(..)返回的状态为HTTP_STATUS_NOT_FOUND,则由于HTTP服务器无法提供数据而停止。
  9. 如果WinHttpQueryHeader(..)返回的状态为HTTP_STATUS_OK,则使用WinHttpQueryDataAvailable(hReq, ..)WinHttpReadData(hReq, ..)检索数据,然后继续执行步骤10.
  10. 如果WinHttpQueryHeader(..)返回的状态为HTTP_STATUS_DENIED,则WinHttpQueryAuthSchemes(hReq, &dwSupportedSchemes, &dwFirstScheme, &dwAuthTarget);选择一种身份验证方法,并使用您的用户名和密码以最简单的方式调用WinHttpSetCredentials(hReq, dwAuthTarget, dwFirstScheme, ..);。成功完成后,请返回步骤4.(如果您第二次来到这里,您的用户名和/或密码无效)
  11. 清理手柄。
  12. 如果你想我可以为此提供代码,但我必须从更大的代码中提取它,这需要一段时间......

    如果服务器使用cookie作为身份验证,由于WinHttp无法处理cookie(或者至少我无法使其正确处理cookie),因此它变得更加复杂。我从后到前搜索过互联网并没有找到答案,但经过漫长的夜晚,我设法得到了一个有效的实施方案(仅适用于我的特殊情况)。

    我希望这个简短的解释有所帮助。如果你需要我的实施,我会在这里发布。

    编辑25 / Oct / 2014:

    看起来我也错过了你的问题!我上面的解释是如何使用身份验证方案。

    这是我从我的实现中提取的一段代码,它发送POST请求并读取响应。我将它与你的例子相匹配,但我没有尝试也没有编译它:

    BOOL bResult;
    DWORD dwRead;
    DWORD dwDownloaded;
    DWORD dwTotalSize;
    char *pBuffer;
    DWORD dwSize;
    DWORD dwStatusCode;
    char buffer[1024 * 128];
    DWORD len;
    
    hRequest = WinHttpOpenRequest(hConnection,
                                  L"POST",
                                  L"http://example.com/dashboard/dashboard.php",
                                  NULL,
                                  WINHTTP_NO_REFERER,
                                  WINHTTP_DEFAULT_ACCEPT_TYPES,
                                  0);
    if (hRequest != NULL)
    {
        len = (DWORD)strlen("username=aan1982&pswd=admin1234&sub_check=1&sub_login=");
        bResult = WinHttpSendRequest(hRequest,
                                     WINHTTP_NO_ADDITIONAL_HEADERS, 
                                     0, 
                                     "username=aan1982&pswd=admin1234&sub_check=1&sub_login=", 
                                     len,
                                     len, 
                                     0);
        if (bResult != FALSE)
        {
            if (WinHttpReceiveResponse(hRequest, NULL) != FALSE)
            {
                dwSize = sizeof(dwStatusCode);
                bResult = WinHttpQueryHeaders(hRequest, 
                                              WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                                              NULL, 
                                              &dwStatusCode, 
                                              &dwSize, 
                                              NULL);
                if (bResult != FALSE)
                {
                    switch (dwStatusCode)
                    {
                    case HTTP_STATUS_OK:
                        pBuffer = buffer;
                        dwTotalSize = 0;
                        do
                        {
                            dwSize = 0;
                            if (WinHttpQueryDataAvailable(hRequest, &dwSize) != FALSE)
                            {
                                dwRead = dwSize;
                                if (dwRead > sizeof(buffer))
                                    dwRead = sizeof(buffer);
    
                                bResult = WinHttpReadData(hRequest,
                                                          pBuffer,
                                                          dwRead,
                                                          &dwDownloaded);
                                if (bResult == FALSE)
                                {
                                    printf("Failed to read data (error: %d)\n", GetLastError());
                                    break;
                                }
                                else
                                {
                                    pBuffer += dwDownloaded;
                                    dwTotalSize += dwDownloaded;
                                }
                            }
                        }
                        while (dwSize > 0);
    
                        /*
                        **  TODO:
                        **  Write buffer to file or process it...
                        */
                        break; /* HTTP_STATUS_OK */
    
                    case HTTP_STATUS_DENIED:
                        printf("access denied!\n");
                        break; /* HTTP_STATUS_DENIED */
    
                    case HTTP_STATUS_NOT_FOUND:
                        printf("file not found\n");
                        break; /* HTTP_STATUS_NOT_FOUND */
    
                    default:
                        printf("WinHttpQueryHeaders(..): dwStatusCode=%d\n", dwStatusCode);
                        break; /* default */
                    } /* switch (dwStatusCode) */
                }
                else /* if (bResult != FALSE) */
                {
                    printf("WinHttpQueryHeaders(..) failed (error: %d)\n", GetLastError());
                }
            }
            else /* if (WinHttpReceiveResponse(hRequest, NULL) != FALSE) */
            {
                printf("WinHttpReceiveResponse(..) failed (error: %d)\n", GetLastError());
            }
        }
        else /* if (bResult != FALSE) */
        {
            printf("Failed to send request (error: %d)\n", GetLastError());
        }
    }
    else /* if (http->hRequest != NULL) */
    {
        printf("Failed to open request (error: %d)\n", GetLastError());
    }
    

    此外,我建议使用HttpFox(FireFox插件)。使用该工具,您可以监控FireFox完成的HTTP请求。这对于了解正在发生的事情很有用,这是开始实施它的好地方。

    让我知道它是否有效......