如何让 Curl 使用与 PHP 浏览器相同的 cookie

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1121280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:09:10  来源:igfitidea点击:

How to let Curl use same cookie as the browser from PHP

phpcurlcookies

提问by Hannes de Jager

I have a PHP script that does an HTTP request on behalf of the browser and the outputs the response to the browser. Problem is when I click the links from the browser on this page it complains about cookie variables. I'm assuming it needs the browsers cookie(s) for the site.

我有一个 PHP 脚本,它代表浏览器执行 HTTP 请求并将响应输出到浏览器。问题是当我单击此页面上浏览器中的链接时,它会抱怨 cookie 变量。我假设它需要网站的浏览器 cookie。

how can I intercept and forward it to the remote site?

如何拦截并将其转发到远程站点?

采纳答案by CtrlX

In fact, it is possible. You just have to take the cookie ofthe browser and pass it as a parameter to curl to mimik the browser. It's like a session Hymaning...

事实上,这是可能的。您只需要获取浏览器的 cookie 并将其作为参数传递给 curl 以模拟浏览器。这就像一个会话劫持......

Here is a sample code:

这是一个示例代码:

// Init curl connection
$curl = curl_init('http://otherserver.com/');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// You can add your GET or POST param

// Retrieving session ID 
$strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';    

// We pass the sessionid of the browser within the curl request
curl_setopt( $curl, CURLOPT_COOKIE, $strCookie ); 

// We receive the answer as if we were the browser
$curl_response = curl_exec($curl);

It works very well if your purpose is to call another website, but this will fail if you call your web server (the same that is launching the curl command). It's because your session file is still open/locked by this script so the URL you are calling can't access it.

如果您的目的是调用另一个网站,它会非常有效,但是如果您调用您的 Web 服务器(与启动 curl 命令相同),这将失败。这是因为您的会话文件仍被此脚本打开/锁定,因此您正在调用的 URL 无法访问它。

If you want to bypass that restriction (call a page on the same server), you have to close the session file with this code before you execute the curl :

如果要绕过该限制(调用同一服务器上的页面),则必须在执行 curl 之前使用以下代码关闭会话文件:

$curl = curl_init('http://sameserver.com/');
//...
session_write_close();
$curl_response = curl_exec($curl);

Hope this will help someone :)

希望这会帮助某人:)

回答by PiTheNumber

This is how I forward all browser cookies to curl and also return all cookies for the curl request back to the browser. For this I needed to solve some problems like getting cookies from curl, parsing http header, sending multiple cookies and session locking:

这就是我将所有浏览器 cookie 转发到 curl 并将 curl 请求的所有 cookie 返回给浏览器的方式。为此,我需要解决一些问题,例如从 curl 获取 cookie、解析 http 标头、发送多个 cookie 和会话锁定:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// get http header for cookies
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

// forward current cookies to curl
$cookies = array();
foreach ($_COOKIE as $key => $value)
{
    if ($key != 'Array')
    {
        $cookies[] = $key . '=' . $value;
    }
}
curl_setopt( $ch, CURLOPT_COOKIE, implode(';', $cookies) );

// Stop session so curl can use the same session without conflicts
session_write_close();

$response = curl_exec($ch);
curl_close($ch);

// Session restart
session_start();

// Seperate header and body
list($header, $body) = explode("\r\n\r\n", $response, 2);

// extract cookies form curl and forward them to browser
preg_match_all('/^(Set-Cookie:\s*[^\n]*)$/mi', $header, $cookies);
foreach($cookies[0] AS $cookie)
{
     header($cookie, false);
}

echo $body;

回答by Ross

From curl_setopt:

来自curl_setopt

By default, libcurl always stores and loads all cookies, independent if they are session cookies or not.

默认情况下,libcurl 始终存储和加载所有 cookie,无论它们是否为会话 cookie。

However you may need to set cookies directly, which can be done using:

但是,您可能需要直接设置 cookie,这可以使用:

curl_setopt($ch, CURLOPT_COOKIE, 'foo=bar');

Which is the same as the Set-Cookie HTTP header. Check you're not using curl_setopt($ch, CURLOPT_COOKIESESSION, true)as this will make libcurl ignore some cookies.

这与 Set-Cookie HTTP 标头相同。检查您没有使用,curl_setopt($ch, CURLOPT_COOKIESESSION, true)因为这会使 libcurl 忽略一些 cookie。

回答by Byron Whitlock

You can't.

你不能。

If you curl the request, you will need to parse the output, and replace all links so they go thru your server.

如果您卷曲请求,您将需要解析输出,并替换所有链接,以便它们通过您的服务器。

  www.yourdomain.com/f?=www.someotherdomain.com/realpage

The only way this would work is if you use persistent cookies in your curl request. CURL can keep cookies itself. Assign a session ID to the cookie file (in curl) so subsequent requests get the same cookies. When a user clicks a link, you will need to curl the request again.

唯一可行的方法是在 curl 请求中使用持久性 cookie。CURL 可以保留 cookie 本身。将会话 ID 分配给 cookie 文件(在 curl 中),以便后续请求获得相同的 cookie。当用户单击链接时,您将需要再次卷曲请求。

It is a security issue to allow site1 to set cookies for site2. Imagine if you could set cookies in the browser for paypal and trick the user into thinking they had logged int or some other malicious action.

允许站点 1 为站点 2 设置 cookie 是一个安全问题。想象一下,如果您可以在浏览器中为 paypal 设置 cookie,并诱使用户认为他们已登录 int 或其他一些恶意操作。

回答by Daff

The Cookie is usually sent with the HTTP request header like

Cookie 通常与 HTTP 请求标头一起发送,例如

Host stackoverflow.com
User-Agent ...
Accept-Language en-us,en;q=0.5
Referer http://stackoverflow.com/unanswered
Cookie bla=blabla;blubb=blu

So I guess that just have to modify the cookie part in your header.

所以我想只需要修改标题中的 cookie 部分。

回答by Vox

PiTheNumber's answer was great but I ran into some issues with it that caused it to still print the headers to the page. So I adjusted it to use the more reliable curl_getinfofunction. This version also follows redirects.

PiTheNumber 的回答很好,但我遇到了一些问题,导致它仍然将标题打印到页面上。所以我调整它以使用更可靠的curl_getinfo功能。此版本也遵循重定向。

public function get_page_content( $url ) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($ch, CURLOPT_HEADER, 1);

    // Forward current cookies to curl
    $cookies = array();
    foreach ($_COOKIE as $key => $value) {
        if ($key != 'Array') {
            $cookies[] = $key . '=' . $value;
        }
    }
    curl_setopt( $ch, CURLOPT_COOKIE, implode(';', $cookies) );

    $destination = $url;

    while ($destination) {
        session_write_close();
        curl_setopt($ch, CURLOPT_URL, $destination);
        $response = curl_exec($ch);
        $curl_info = curl_getinfo($ch);
        $destination = $curl_info["redirect_url"];
        session_start();
    }
    curl_close($ch);

    $headers = substr($response, 0, $curl_info["header_size"]);
    $body = substr($response, $curl_info["header_size"]);

    // Extract cookies from curl and forward them to browser
    preg_match_all('/^(Set-Cookie:\s*[^\n]*)$/mi', $headers, $cookies);
    foreach($cookies[0] AS $cookie) {
        header($cookie, false);
    }

    return $body;
}