【发布时间】:2010-11-10 09:55:36
【问题描述】:
我有一个 PHP 脚本,它代表浏览器执行 HTTP 请求并将响应输出到浏览器。问题是当我单击此页面上浏览器的链接时,它会抱怨 cookie 变量。我假设它需要网站的浏览器 cookie。
如何拦截并转发到远程站点?
【问题讨论】:
我有一个 PHP 脚本,它代表浏览器执行 HTTP 请求并将响应输出到浏览器。问题是当我单击此页面上浏览器的链接时,它会抱怨 cookie 变量。我假设它需要网站的浏览器 cookie。
如何拦截并转发到远程站点?
【问题讨论】:
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
所以我想只需要修改标题中的 cookie 部分。
【讨论】:
来自curl_setopt:
默认情况下,libcurl 始终存储和加载所有 cookie,无论它们是否是会话 cookie。
但是您可能需要直接设置 cookie,可以使用:
curl_setopt($ch, CURLOPT_COOKIE, 'foo=bar');
这与 Set-Cookie HTTP 标头相同。检查你没有使用curl_setopt($ch, CURLOPT_COOKIESESSION, true),因为这会使 libcurl 忽略一些 cookie。
【讨论】:
你不能。
如果您 curl 请求,您将需要解析输出,并替换所有链接,以便它们通过您的服务器。
www.yourdomain.com/f?=www.someotherdomain.com/realpage
唯一可行的方法是在 curl 请求中使用持久性 cookie。 CURL 可以自己保存 cookie。将会话 ID 分配给 cookie 文件(在 curl 中),以便后续请求获得相同的 cookie。当用户点击链接时,您需要再次 curl 请求。
允许site1 为site2 设置cookie 是一个安全问题。想象一下,如果您可以在浏览器中为 paypal 设置 cookie,并诱使用户认为他们已登录 int 或其他恶意操作。
【讨论】:
事实上,这是可能的。您只需获取浏览器的 cookie 并将其作为参数传递给 curl 以模仿浏览器。 这就像一个会话劫持......
这是一个示例代码:
// 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);
如果您的目的是调用另一个网站,它工作得很好,但是如果您调用您的网络服务器(与启动 curl 命令相同),这将失败。这是因为您的会话文件仍被此脚本打开/锁定,因此您调用的 URL 无法访问它。
如果您想绕过该限制(调用同一服务器上的页面),则必须在执行 curl 之前使用此代码关闭会话文件:
$curl = curl_init('http://sameserver.com/');
//...
session_write_close();
$curl_response = curl_exec($curl);
希望这会对某人有所帮助:)
【讨论】:
这就是我将所有浏览器 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;
【讨论】:
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;
}
【讨论】: