如何使用 libcurl 登录本网站? (C++)

How do I use libcurl to log into this website? (C++)

我想制作一个 C++ 程序来填写带有登录凭据的 HTML 网络表单(我目前将其硬编码到用户名和密码字段中),然后提交该网络表单并进入下一个 HTML页。

使用下面的代码,它一直卡在登录页面上,无法前进。在控制台中,我一直在获取登录页面的 HTML 源代码,而不是登录后出现的页面。

有人可以一步步指导我吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

int main()
{
    curl_global_init( CURL_GLOBAL_ALL );
    CURL * myHandle = curl_easy_init ( );

    // Set up a couple initial paramaters that we will not need to mofiy later.
    curl_easy_setopt(myHandle, CURLOPT_USERAGENT, "Mozilla/5.0");
    curl_easy_setopt(myHandle, CURLOPT_AUTOREFERER, 1 );
    curl_easy_setopt(myHandle, CURLOPT_FOLLOWLOCATION, 1 );
    curl_easy_setopt(myHandle, CURLOPT_COOKIEFILE, "");

    // Visit the login page once to obtain a PHPSESSID cookie
    curl_easy_setopt(myHandle, CURLOPT_URL, "website login page URL here");
    curl_easy_perform( myHandle );

    // Now, can actually login. First we forge the HTTP referer field, or HTS will deny the login
    curl_easy_setopt(myHandle, CURLOPT_REFERER, "website login page URL here");
    // Next we tell LibCurl what HTTP POST data to submit
    char *data="ctl00$LoginTextBox=USERNAME&ctl00$PasswordTextbox=PASSWORD&ctl00$LogInButton=Sign in&ctl00$HiddenValue=Initial Value";
    curl_easy_setopt(myHandle, CURLOPT_POSTFIELDS, data);
    curl_easy_perform( myHandle );
    curl_easy_cleanup( myHandle );
    return 0;
}

这是我正在处理的 HTML 网络表单:

<div id="loginForm">
    <div id="loginInput">
        <label for="ctl00_LoginTextBox" id="ctl00_LoginLabel">Name/Badge</label>
        <input name="ctl00$LoginTextBox" type="text" id="ctl00_LoginTextBox" class="PopupInput" />
    </div>
    <div id="passwordInput">
        <label for="ctl00_PasswordTextbox" id="ctl00_PasswordLabel">Password</label>
        <input name="ctl00$PasswordTextbox" type="password" id="ctl00_PasswordTextbox" class="PopupInput" />        
    </div>
    <div id="equipmentbox">

    </div>
</div>

<div id="ctl00_LoginButtons">
    <input type="submit" name="ctl00$LogInButton" value="Sign in" id="ctl00_LogInButton" class="btn" />
    <input type="submit" name="ctl00$SwitchLoginScreenModeBT" value="Change Password" id="ctl00_SwitchLoginScreenModeBT" class="btn" /> 
</div>

<input name="ctl00$HiddenValue" type="hidden" id="ctl00_HiddenValue" value="Initial Value" />
<input name="ctl00$HiddenValue2" type="hidden" id="ctl00_HiddenValue2" value="Initial Value" />

您的代码有两个问题:

  • 您的 data 未正确 url 完全编码。您可以(并且应该)使用 curl_easy_escape() 正确编码每个 name=value 对的每个 namevalue 组件,您 post 和 CURLOPT_POSTFIELDS

  • 您正在 posting data 使用 CURLOPT_POSTFIELDS,其中 post 格式为 application/x-www-form-urlencoded(这是许多网络表单在线),但所讨论的特定网络表单实际上期望 datamultipart/form-data 格式 posted 而不是(由于网络表单的 enctype="multipart/form-data" 属性),所以你需要使用 CURLOPT_HTTPPOST (deprecated) or CURLOPT_MIMEPOST 代替。

试试像这样的东西:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

int main()
{
    curl_global_init(CURL_GLOBAL_ALL);
    CURL *myHandle = curl_easy_init();

    // Set up a couple initial paramaters that we will not need to mofiy later.
    curl_easy_setopt(myHandle, CURLOPT_USERAGENT, "Mozilla/5.0");
    curl_easy_setopt(myHandle, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(myHandle, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(myHandle, CURLOPT_COOKIEFILE, "");

    // Visit the login page once to obtain a PHPSESSID cookie
    curl_easy_setopt(myHandle, CURLOPT_URL, "website login page URL here");
    curl_easy_perform(myHandle);

    // Now, can actually login. First we forge the HTTP referer field, or HTS will deny the login
    curl_easy_setopt(myHandle, CURLOPT_REFERER, "website login page URL here");

    // Next we tell LibCurl what HTTP POST data to submit
    struct curl_httppost *data = NULL;
    struct curl_httppost *last = NULL;

    curl_formadd(&data, &last, CURLFORM_PTRNAME, "ctl00$LoginTextBox", CURLFORM_PTRCONTENTS, "USERNAME", CURLFORM_END);
    curl_formadd(&data, &last, CURLFORM_PTRNAME, "ctl00$PasswordTextbox", CURLFORM_PTRCONTENTS, "PASSWORD", CURLFORM_END);
    curl_formadd(&data, &last, CURLFORM_PTRNAME, "ctl00$LogInButton", CURLFORM_PTRCONTENTS, "Sign in", CURLFORM_END);
    curl_formadd(&data, &last, CURLFORM_PTRNAME, "ctl00$HiddenValue", CURLFORM_PTRCONTENTS, "Initial Value", CURLFORM_END);
    curl_easy_setopt(myHandle, CURLOPT_HTTPPOST, data);

    curl_easy_perform(myHandle);

    curl_formfree(data);
    curl_easy_cleanup(myHandle);

    return 0;
}

或者这个:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

int main()
{
    curl_global_init(CURL_GLOBAL_ALL);
    CURL *myHandle = curl_easy_init();

    // Set up a couple initial paramaters that we will not need to mofiy later.
    curl_easy_setopt(myHandle, CURLOPT_USERAGENT, "Mozilla/5.0");
    curl_easy_setopt(myHandle, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(myHandle, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(myHandle, CURLOPT_COOKIEFILE, "");

    // Visit the login page once to obtain a PHPSESSID cookie
    curl_easy_setopt(myHandle, CURLOPT_URL, "website login page URL here");
    curl_easy_perform(myHandle);

    // Now, can actually login. First we forge the HTTP referer field, or HTS will deny the login
    curl_easy_setopt(myHandle, CURLOPT_REFERER, "website login page URL here");

    // Next we tell LibCurl what HTTP POST data to submit
    curl_mime *mime = curl_mime_init(myHandle);

    curl_mimepart *part = curl_mime_addpart(mime);
    curl_mime_name(part, "ctl00$LoginTextBox");
    curl_mime_data(part, "USERNAME", CURL_ZERO_TERMINATED);

    part = curl_mime_addpart(mime);
    curl_mime_name(part, "ctl00$PasswordTextbox");
    curl_mime_data(part, "PASSWORD", CURL_ZERO_TERMINATED);

    part = curl_mime_addpart(mime);
    curl_mime_name(part, "ctl00$LogInButton");
    curl_mime_data(part, "Sign in", CURL_ZERO_TERMINATED);

    part = curl_mime_addpart(mime);
    curl_mime_name(part, "ctl00$HiddenValue");
    curl_mime_data(part, "Initial Value", CURL_ZERO_TERMINATED);

    curl_easy_setopt(myHandle, CURLOPT_MIMEPOST, data);

    curl_easy_perform(myHandle);

    curl_mime_free(mime);
    curl_easy_cleanup(myHandle);

    return 0;
}