为什么CURLOPT_COOKIEJAR以某种方式保存了与Set cookie标头不同的cookie值


Why is CURLOPT_COOKIEJAR somehow saving different cookie values than the Set-Cookie header?

TL;DR:

我有一些非常简单的PHP代码,利用cURL发出单个HTTP请求(在实践中,向Diaspora*pod发出请求,尽管这与问题无关)。该代码记录web服务器返回的任何cookie,然后手动将这些值设置为libcurl的CURLOPT_COOKIE。然而,在试图查找错误时,我发现当我使用CURLOPT_COOKIEFILECURLOPT_COOKIEJAR时,cookie文件中的cookie值与使用CURLOPT_COOKIE时不同。为什么会出现这种情况?(参见下面的代码。)

前期研究

我已经研究过其他问题,比如这个问题,它提出了各种方法来操纵libcurl的选项,以保持相同的资源句柄和内存中的cookie,但这不适合我的应用程序。我需要直接访问cookie值,尤其是文件系统上的而不是(将它们保存到数据库中,但同样,这与问题无关)。

代码

为了完整起见,下面是我正在使用的代码的测试用例:

<?php
// This function simply extracts the cookie set by a webserver by looking at the full HTTP source traffic.
function readCookie ($str) {
    $m = array();
    preg_match('/Set-Cookie: (.*?);/', $str, $m);
    return (!empty($m[1])) ? $m[1] : false;
}
// This function does the same for the CSRF token required for login.
function parseAuthenticityToken ($str) {
    $m = array();
    preg_match('/content="(.*?)" name="csrf-token"/', $str, $m);
    return (!empty($m[1])) ? $m[1] : false;
}
// Get first page, to find the CSRF token.
$ch = curl_init('https://diasp.org/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
curl_close($ch);
$csrf_token = parseAuthenticityToken($resp);
$params = array(
    'user[username]' => 'my_username',
    'user[password]' => 'my_password',
    'authenticity_token' => $csrf_token
);
// Make POST request to the log in controller.
$ch = curl_init('https://diasp.org/users/sign_in');
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// In order to work, the COOKIEFILE/JAR options must be used. Why?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
//curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($resp);
$cookies = readCookie($resp);
// Even if the login is successful, this fails if and only if no COOKIEFILE/JAR is specified.
// Why?
$ch = curl_init('https://diasp.org/stream');
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// If I use COOKIEFILE here, the request works. What is this line doing that CURLOPT_COOKIE is not?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($ch);
var_dump($resp);

摘要

我正在对web服务器进行非常简单、循序渐进的过程调用。这些请求一个接一个地发出,结果输出(整个HTTP会话的输出,包括标头)保存在一个变量中,然后读取该变量,并从Set-CookieHTTP标头行解析Cookie的值。但是,如果这些行未被注释,那么这些值永远不会与libcurl写入COOKIEFILE的值相同。

CURLOPT_COOKIE我做错了什么,或者CURLOPT_COOKIEFILECURLOPT_COOKIEJAR选项没有做错什么?它是以某种可逆的方式编码还是解码的?提前谢谢。

您可能没有注意到CURLOPT_COOKIE和CURLOPT_COOKIELIST/FILE/JAR之间的区别。两者都处理COOKIE,但CURLOPT_COOKIE不会将您这次设置的COOKIE存储在内存中,也不会将其存储在CURLOPT_COOKIEJAR指定的COOKIE文件中;相反,CURLOPT_COOKIELIST会这样做。

libcurl中有一种称为cookie引擎的机制。当您设置CURLOPT_COOKIELIST/FILE/JAR中的任何一个时,它就会被触发启用,libcurl负责在所有后续会话中发送/解析/读取/存储cookie。

CURLOPT_COOKIE只是一种一次性设置额外COOKIE的快速破解方法。