PHP: CURL 无法保存 cookie

PHP: CURL fails to save cookie

我正在使用一台主机的 PHP 连接到同一子网中另一台主机的 API,这需要 cookie 来记住登录。它给了我一个WARNING: failed to save cookies in /var/includes/cookie。 我为自己设置了一个简短的测试脚本如下:

$handle = curl_init();
$logfile = fopen('php://temp', 'w+');

curl_setopt_array($handle, array(
    CURLOPT_URL             => 'https://10.0.0.10:8443/api/login',
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_COOKIEJAR       => '/var/includes/cookie',
    CURLOPT_COOKIEFILE      => '/var/includes/cookie',
    CURLOPT_SSL_VERIFYPEER  => false,
    CURLOPT_SSL_VERIFYHOST  => false,
    CURLOPT_VERBOSE         => true,
    CURLOPT_STDERR          => $logfile,
    CURLOPT_POST            => true,
    CURLOPT_POSTFIELDS      => json_encode(array('username' => 'user', 'password' => 'pass'))
));

$output = curl_exec($handle);
curl_close($handle); // Cookies should technically be saved here, right?

// Get contents from curl verbose log file
rewind($logfile);
$log = stream_get_contents($logfile);
fclose($logfile);
error_log($log);

error_log(print_r($output, true));

详细日志文件给我这个输出:

* Hostname in DNS cache was stale, zapped
*   Trying 10.0.0.10...
* TCP_NODELAY set
* Connected to 10.0.0.10 (10.0.0.10) port 8443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=api.example.com
*  start date: Oct  5 07:07:04 2020 GMT
*  expire date: Jan  3 07:07:04 2021 GMT
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> POST /api/login HTTP/1.1
Host: 10.0.0.10:8443
Accept: */*
Content-Length: 42
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 42 out of 42 bytes
< HTTP/1.1 200
< vary: Origin
< Access-Control-Allow-Credentials: true
< Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
* Added cookie xxx="some_session_id" for domain 10.0.0.10, path /, expire 0
< Set-Cookie: xxx=some_session_id; Path=/; Secure; HttpOnly
* Added cookie yyy="some_other_id" for domain 10.0.0.10, path /, expire 0
< Set-Cookie: yyy=some_other_id; Path=/; Secure
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Content-Length: 30
< Date: Mon, 16 Nov 2020 12:28:42 GMT
<
* Connection #0 to host 10.0.0.10 left intact
* WARNING: failed to save cookies in /var/includes/cookie

$output本身的内容是正确的;它给了我来自 API 的 OK 信号,表明登录成功。然而,随后的请求给我的信号是我没有登录,当然是因为 cookie 没有被保存,因此没有被读取。

我试过:

有什么我应该看的地方吗? SELinux 会影响这个吗?我的问题看起来类似于 this one

CentOS 8,PHP7.2.11,libcurl 7.61.1

事实证明, SELinux 的尝试。提到问题的解决方案感觉有点傻,但我知道我不是第一个被 SELinux 绊倒的人。

首先,为了测试这是否真的是问题所在,您可以暂时将其关闭(如果这样做对您来说是安全的)。

setenforce 0

如果可行,我当然会建议将其重新打开,而不是为需要修改的文件设置规则。

setenforce 1

因为我在 /var/includes/cookie 有文件,所以我会 运行 以下命令来添加持久规则:

semanage fcontext -a -t httpd_sys_rw_content_t /var/includes/cookie
  • -a 添加一条记录
  • -t 指定了一种新类型,在本例中为可由 httpd
  • 写入的类型

编写上下文规则后,仍需应用它:

restorecon -v /var/includes/cookie
  • -v 以获得关于更改内容的一些输出

有关更深入的说明,请参阅 this guide

另外值得注意:我必须安装 policycoreutils-python-utils 软件包才能在我的最小 CentOS 系统上获取 semanage 命令。