【问题标题】:PHP CURL not following redirect even though CURLOPT_FOLLOWLOCATION is set to true即使 CURLOPT_FOLLOWLOCATION 设置为 true,PHP CURL 也不遵循重定向
【发布时间】:2019-08-28 15:49:30
【问题描述】:

我正在尝试在 PHP 中重现以下内容:

curl -X GET "https://example.com/webservice" --user <Sender ID>:<password> -H  "accept: text/plain"

这是我目前所拥有的:

$this->ch = curl_init();
curl_setopt_array( $this->ch, array(
CURLOPT_URL => 'https://example.com/webservice',
CURLOPT_HTTPHEADER => 'accept: text/plain',
CURLOPT_HTTPAUTH => CURLAUTH_ANY,
CURLOPT_USERPWD => $this->sender_id . ':' . $this->password,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT=>10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT=>20 ) );
$result = curl_exec( $this->ch );

当我使用 curl_getinfo() 时,我看到状态代码 302 并且 REDIRECT_URL 是 https://example.com/webservice/ 所以看起来重定向没有被遵循。我期待状态代码 200 和 REDIRECT_URL 为空。我尝试通过浏览器访问网络服务。它提示输入密码,然后在输入密码后,浏览器成功重定向。我错过了什么?

VERBOSE 输出(带有屏蔽的 URL):

* Re-using existing connection! (#0) with host example.com
* Connected to example.com (216.81.87.19) port 443 (#0)
> GET /webservice HTTP/1.1
Host: example.com
Accept: */*

< HTTP/1.1 302 
< Date: Wed, 28 Aug 2019 17:25:33 GMT
< Server: Apache/2.4.39 (Unix) OpenSSL/1.0.2r
< Public-Key-Pins: pin-sha256="iWMi9jzvh3eEA6d6V1rooHD5721iut3mUupum14lLv4="; max-age=2592000; includeSubDomains
< Webfarm_Build_Host: WebFarm Build Ran on xxxxxxxxx.example.com
< Webfarm_Build_Date: Mon Jun 10 19:15:50 EDT 2019
< Webfarm_Version: Release-V12
< Webfarm_SSO_Agent: DMZWEBFARM
< Webfarm_SSO_Agent_Mode: simple
< Webgate_Product: Oracle_Access_Manager
< Webgate_Component: WebGate
< Webgate_Webserver: APACHE2.2/2.4
< Webgate_Webserver_OpenSSL_Version: OpenSSL 1.0.2r 26 Feb 2019
< Webgate_Platform: linux64
< Webgate_Language_Type: en-us
< Webgate_Version_Release: 11.1.2.3.0 
< Webgate_Version_Release_Date: 07/01/2016
< X-Frame-Options: SAMEORIGIN
< Location: https://example.com/webservice/
< X-XSS-Protection: 1; mode=block
< Content-Length: 0
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Proxy-Connection: Keep-Alive
< Connection: Keep-Alive
< Set-Cookie: EDME_EAPIS_PRD_apache-llb=!KgEF2eiXGNLd6aDBees2zCqa01Pqg/9GbgMNYbuHA7Jzql7b1eBMCnS5PyhwShD5S+nUZWKbTBYH9eY=; path=/; Httponly; Secure
< 
* Curl_http_done: called premature == 0
* Connection #0 to host example.com left intact

【问题讨论】:

  • stackoverflow.com/a/28458522/2776343 的可能重复项?
  • 那个似乎不适用。他忘记使用 curl_exec。另外,我确实将 CURLOPT_FOLLOWLOCATION 设置为 true。我没有设置 open_basedir,也不是安全模式。
  • 但是第二个回复@George? $redirectURL = curl_getinfo($this->ch,CURLINFO_EFFECTIVE_URL );
  • CURLINFO_EFFECTIVE_URL 是我指定的 URL,即 https://example.com/webservice
  • 向我们展示 curl 详细日志。 $tmp=tmpfile();curl_setopt_array($ch,[CURLOPT_VERBOSE=&gt;1,CURLOPT_STDERR=&gt;$tmp]);curl_exec($ch);/*https://bugs.php.net/bug.php?id=76268*/rewind($tmp);var_dump(stream_get_contents($tmp));

标签: php curl redirect


【解决方案1】:

如果您处于安全模式或设置了 open_basedir,则需要执行以下操作(调整以适应):

function curlWithFollow($ch)
{
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $content = curl_exec($ch);
    $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (in_array($httpStatus, [301, 302]) {
        preg_match('/(Location:|URI:)(.*?)\n/', $data, $matches);

        if (isset($matches[2])) {
            $redirectUrl = trim($matches[2]);

            if ($redirectUrl !== '') {
                curl_setopt($ch, CURLOPT_URL, $redirectUrl);
                return curlWithFollow($ch);
            }
        }
    }

    return $content;
}

这样称呼它:

$ch = curl_init($url);
$content = curlWithFollow($ch);
curl_close($ch);

【讨论】:

  • safe_mode 已关闭且 open_basedir 未设置。
  • 我想我可以将 FOLLOW_LOCATION 设置为 false 并使用您的技术使其工作。但为什么它没有按我预期的方式工作?
  • ...iirc、libcurl 和 php curl_api 不关心 safe_mode 也不关心 open_basedir
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多