【问题标题】:PHP Curl ignoring CURLOPT_COOKIEFILE on META REFRESH redirectsPHP Curl 忽略 META REFRESH 重定向上的 CURLOPT_COOKIEFILE
【发布时间】:2021-09-29 12:47:26
【问题描述】:

好的,伙计们,我会尽量让这个问题尽可能简单(我这几天都在努力发现这个问题):

我有这个功能

function readContent($url, $sessionId)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    $cookiesFile = realpath(__DIR__.'/cookies/'.$sessionId.'.txt');
    if(file_exists($cookiesFile))
    {
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiesFile);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiesFile);
    }
    
    //DEBUG------------------------------------------------------------------
    $debugFile = fopen(__DIR__.'/debug/'.$sessionId.'.txt', 'w');
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_STDERR, $debugFile);
    //-----------------------------------------------------------------------

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);   
    try
    {
        $output = curl_exec($ch);       
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if($httpCode == 200)
        {
            file_put_contents(__DIR__.'/contents/'.$sessionId.'.html', $output);
            curl_close($ch);
            preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $output, $match);
            if (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1)
            {
                return readContent(str_replace('&amp;', '&', $match[1][0]), $sessionId);
            }
        }
    }
    catch(Exception $e)
    {
        return false;
    }
}

它执行 3 个请求(来自 STDERR 文件的日志):

GET /redacted/ HTTP/2
Host: redacted.coom
accept: */*

< HTTP/2 302 
< location: https://redacted.com/location1/
* Added cookie redacted="redacted" for domain redacted.com, path /, expire 1634127679
< set-cookie: redacted=redacted; path=/; expires=Wed, 13 Oct 2021 12:21:19 GMT; SameSite=Lax
multiple set-cookie / added cookie follows...

所以第一个请求是在没有任何 cookie 的情况下完成的,但它在 COOKIEFILE/COOKIEJAR 中设置了多个 cookie。一旦 CURL 遵循请求应答中指定的位置,它就会发送所有 cookie 集:

* Ignoring the response-body
* Connection #0 to host redacted.com left intact
* Issue another request to this URL: 'https://redacted.com/location1/'
> GET /location1/ HTTP/2
Host: redacted.com
accept: */*
cookie: redacted=redacted;redacted=redacted;redacted=redacted......

< HTTP/2 200 

第二个请求在 html 正文中返回 200 OK 和 META REFRESH。 正如您在函数中看到的,如果它使用 META REFRESH 正则表达式检测到 200,则该函数会自行调用在 META REFRESH 上传递 URL。它去第三个请求,但这一次,它只发送了 1 个 cookie

> GET /location1/?from_meta_refresh=1 HTTP/2
Host: redacted.com
accept: */*
cookie: redacted=redacted

这是对该页面的无效请求,因为它需要另一个已设置且位于 CURLOPT_COOKIEFILE 上但未发送的 cookie。 这个唯一发送的 cookie 是 COOKIEFILE 的最后一行。我认为这可能是 cookie 上的一些参数,例如域/文件夹/安全,但我注意到文件上有另一个 cookie,具有完全相同的参数,而不是在此请求中发送:

redacted.com    FALSE   /   FALSE   1634128519  not_sent    redacted
redacted.com    FALSE   /   FALSE   1634128519  sent    redacted

请帮忙!

【问题讨论】:

    标签: php curl


    【解决方案1】:

    由于某些未知原因,当您调用 curl_close() 时,PHP Curl 不会将 cookie 保存到 COOKIEJAR 文件中。所以我需要在关闭之前保存 cookie,使用:

    curl_setopt($ch, CURLOPT_COOKIELIST, 'FLUSH');

    在此之后,cookie 可用于下一个请求。

    【讨论】:

      猜你喜欢
      • 2017-08-09
      • 2011-07-20
      • 2016-11-08
      • 2011-03-24
      • 2017-05-25
      • 1970-01-01
      • 2013-02-14
      • 2017-03-02
      相关资源
      最近更新 更多