如何使用 curl 登录 Stack Exchange?

Posted

技术标签:

【中文标题】如何使用 curl 登录 Stack Exchange?【英文标题】:How can I log in to Stack Exchange using curl? 【发布时间】:2017-10-24 13:24:30 【问题描述】:

我想从终端登录远程网站,需要用户名和密码才能登录。

所以我首先尝试登录到 Stack Exchange 站点之一。 According to this answer,您使用 -u username:password 添加您的凭据。

所以我尝试了以下方法:

USERNAME="mine@gmail.com"
PASSWORD="myPassword"

URL="https://sustainability.stackexchange.com/"
curl $URL -u $USERNAME:$PASSWORD

但是生成的网站不是登录用户看到的页面,而是未经验证的用户看到的页面,显示了一个注册按钮。

我认为它仅适用于您在尝试访问时显示的弹出窗口中输入凭据的情况。

那么在这些情况下,我该如何从终端中登录?

【问题讨论】:

curl 的-u USER:PASS 选项将使用基本身份验证,这不是大多数网站处理身份验证的方式。请参阅下面的答案。 【参考方案1】:

您可以通过浏览器的工具来完成。您需要通过Chrome浏览器>查看> javascript控制台>网络>(右键单击)>复制选项菜单>单击选择“复制为cURL”来复制带有所有标题的cookie:

通常我们以这种方式卷曲:

curl -c cookie.txt -d "LoginName=username" -d "password=changepassword" https://examplesite/a
curl -b cookie.txt https://examplesite/b

通过右键复制会非常大(当然我改变了一些东西以防止自己被黑客入侵):

curl 'https://meta.***.com/' -H 'pragma: no-cache' -H 'accept-encoding: gzip, deflate, sdch, br' -H 'accept-language: en-US,en;q=0.8' -H 'upgrade-insecure-requests: 1' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/58.0.3029.110 Safari/537.36' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'cache-control: no-cache' -H 'authority: meta.***.com' -H 'cookie: prov=xxxxxxxxxxx; __qca=P0-xxxxxxx-xxxxxx; acct=t=xxxxxxxxxxxx; _ga=GA1.2.xxxxxxxx; _gid=GA1.2.xxxxxxx; _ga=GA1.3.xxxxxxx; _gid=xxxxxxxxx9' -H 'referer: https://meta.***.com/' --compressed

【讨论】:

技术上不使用 curl 登录,而是使用浏览器中现有的已登录 cookie 会话获取首页。一旦 cookie 会话到期,或者他在浏览器中注销,它也会停止工作,以先到者为准。 @hanshenrik 请测试这个脚本——pastebin.com/raw/DwCWH9fB。注意第一个命令重定向的位置。第二个命令 (curl -X POST) 将具有该 URL。 您需要 openID 才能登录。我从 Lynx 测试过 这对我不起作用。我从 curl 中获得了hackershake 个人资料的注销 HTML。见这里pastebin.com/QFVR0YXy。另外,我看不到该代码是如何工作的,因为在执行 curl -X GET 'https://sustainability.stackexchange.com/users/login' 时,您不会从 html 中提取 csrf 登录密钥(称为 <input type="hidden" name="fkey" value="??????????"> ),而在执行登录 POST 请求时需要 另外,不,你不需要 openID 来登录.. 至少我下面的 php 脚本在没有 openID 的情况下登录【参考方案2】:

不幸的是,登录协议比这复杂得多,并且不是 curl 内置的方案。这不是 curl 的工作,而是一些脚本语言(如 PHP 或 Python),尽管 libcurl 对管理 http 协议和 cookie 等有很大帮助。 libxml2 将有助于解析隐藏在 HTML 中的登录 CSRF 密钥。他们可能需要一个引用标题,他们甚至可能检查引用标题是真实的,而不是伪造的(idk,但这不会让我感到惊讶)。

首先,向https://sustainability.stackexchange.com/users/login 发出普通的普通HTTP GET 请求,并确保保存cookie 和html 响应。现在提取 POST URL 和 ID 为 login-form 的表单的输入元素,这包括 CSRF 令牌、用户名和密码,以及其他一些。然后向https://sustainability.stackexchange.com/users/login发出application/x-www-form-urlencoded编码的POST请求,使用从第一个GET请求中收到的cookie,以及您提取的所有<input元素的POST数据,记得填写“电子邮件”和“密码”输入。

现在您应该获取登录的 html,并且要继续获取页面的登录版本,请确保将相同的 cookie 会话 id 应用于下一个 http 请求(它的这个 cookie 会话 id 使网站记得你是那个登录那个账号的人~)

这是 PHP 中的一个示例,使用 libcurl 和 libxml2(使用 PHP 的 DOMDocument 作为 libxml2 的便捷包装器,并使用来自https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php 的 hhb_curl 作为 libcurl 的便捷包装器,处理 cookie、引用、libcurl 错误处理(转静默 libcurl 错误到异常中,等等),最后,它转储登录的 HTML,证明它已登录。(并且提供的电子邮件/密码是用于测试的虚拟帐户,它没有问题被泄露,当我在这里发布凭据时显然会发生这种情况。):

<?php
declare(strict_types = 1);
require_once ('hhb_.inc.php');
$hc = new hhb_curl ( 'https://sustainability.stackexchange.com/users/login', true );
// getting a cookie session, CSRF token, and a referer:
$hc->exec ();
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut () );
$domd = @DOMDocument::loadHTML ( $hc->getResponseBody () );
$inputs = array ();
$form = $domd->getElementById ( "login-form" );
$url = $form->getAttribute ( "action" );
if (! parse_url ( $url, PHP_URL_HOST )) 
    $url = 'https://' . rtrim ( parse_url ( $hc->getinfo ( CURLINFO_EFFECTIVE_URL ), PHP_URL_HOST ), '/' ) . '/' . ltrim ( $url, '/' );

// hhb_var_dump ( $url, $hc->getStdErr (), $hc->getStdOut () ) & die ();

foreach ( $form->getElementsByTagName ( "input" ) as $input ) 
    if (false !== stripos ( $input->getAttribute ( "type" ), 'button' ) || false !== stripos ( $input->getAttribute ( "type" ), 'submit' )) 
        // not sure why, but buttones, even ones with names and values, are ignored by the browser when logging in,
        // guess its safest to follow suite.
        continue;
    
    // var_dump ( $input->getAttribute ( "type" ) );
    $inputs [$input->getAttribute ( "name" )] = $input->getAttribute ( "value" );

assert ( ! empty ( $inputs ['fkey'] ), 'failed to extract the csrf token!' );
$inputs ['email'] = 'vs5jkqyx4hw3seqr@my10minutemail.com';
$inputs ['password'] = 'TestingAccount123';
$hc->setopt_array ( array (
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
        CURLOPT_URL => $url 
) );
$hc->exec ();

hhb_var_dump ( $inputs, $hc->getStdErr (), $hc->getStdOut () );

有趣的注意,默认情况下,libcurl 在 POST 请求中使用 multipart/form-data-encoding,但是这个站点(实际上是大多数站点)在 POST 请求中使用 application/x-www-form-urlencoded-encoding。这里我使用 PHP 的 http_build_query() 将 POST 数据编码为 application/x-www-form-urlencoded-format

【讨论】:

他从未在 curl 中提及 PHP。他想在终端做。 @SagarV 我告诉他他需要做什么。但我没有为他编写实现。如果你想从 bash 中解析 HTML,请继续,为他实现它,但我肯定不想从终端解析 HTML。 在这些情况下如何从终端登录这是他的问题。我想你错过了 @SagarV 不,我没有。通过安装 php-cli 并运行 php script.php,这段 php 代码可以从终端完美执行【参考方案3】:

登录网址不是https://sustainability.stackexchange.com/,而是https://sustainability.stackexchange.com/users/login

你提到的链接说

curl -u username:password $URL

不是

curl $URL -u username:password

试试

USERNAME="mine@gmail.com"
PASSWORD="myPassword"

URL="https://sustainability.stackexchange.com/users/login"
curl -u $USERNAME:$PASSWORD $URL

更新

Stack Exchange 需要一个额外的登录密钥,称为fkey。如果您从浏览器检查登录表单,您可以看到名称为 fkeyhidden 输入字段,其值为哈希值。它是识别会话并防止虚假登录尝试所必需的。

【讨论】:

我在 7 天前的帖子中确实说过这一点。 >now extract the POST URL and input elements of the form with id login-form, this includes the CSRF token, username, and password, and bunch of others >>>assert ( ! empty ( $inputs ['fkey'] ), 'failed to extract the csrf token!' );【参考方案4】:

如果您(使用 Chrome)查看登录页面上的登录表单(右键单击、检查、查看 html),您会了解到该表单正在将 emailpassword 字段发布到 https://sustainability.stackexchange.com/users/login

使用 curl 的方法是:

curl https://sustainability.stackexchange.com/users/login -d "email=test@test.com&password=monkey"

如果你仔细研究返回的 html,你会发现这是一个无效的登录。

问题在于,如果您想在后续调用中使用登录会话,则需要存储从站点获取的会话 cookie 以便进行后续调用。查看 curl 手册页,您可以看到有一个 -c &lt;cookie_jar_file&gt; 选项。如果您使用文件名将其传入,它应该会保存登录调用中的 cookie,并且您应该能够使用已建立的会话进行后续调用,并且您应该正在开展业务。

编辑: 此处的其他答案和 cmets 指出了此答案中缺少的一些内容。有必要获取并随后发布 csrf 密钥以及发布的正确 MIME 类型。当然可以在命令行上执行此操作,但使用更完整的语言会容易得多(根据接受的答案)。我确实发现了这个问题,该问题对可能用于删除使其工作所需的 HTML/XML sn-ps 的工具提出了建议:https://superuser.com/questions/528709/command-line-css-selector-tool/528728

【讨论】:

以上是关于如何使用 curl 登录 Stack Exchange?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 curl 登录 Graphene Django 应用程序?

使用 PHP 和 Curl 登录 Google,Cookie 已关闭?

使用 cURL 注销应用程序

PHP cURL 没有存储会话 cookie...如何解决这个问题?

如何在curl php中发送第二个请求时保留会话?

尝试使用 Curl 登录网站