【问题标题】:HTTP Requests made with file_get_contents() share the same session data?使用 file_get_contents() 发出的 HTTP 请求共享相同的会话数据?
【发布时间】:2014-05-28 21:24:41
【问题描述】:

我有问题...

我有一个类似 MVC 的框架,并且重定向机制允许我在远程主机上获取 PHP 生成的 HTML 代码的 sn-ps。

我通过使用 file_get_contents() 函数获取这些 sn-ps,并打开了 allow_url_fopen。

问题是我在这些代码片段中使用了会话数据,并且每次都会丢失会话数据。我假设这个新请求没有共享相同的会话数据,因此我需要一种方法来获取这些片段而不会丢失我的会话数据。

有什么建议吗?

【问题讨论】:

  • 等等...您正在使用远程 file_get_contents 调用作为包含?就像您从网站获取 PHP 源代码然后执行它一样?
  • 很有趣,但我们需要了解更多细节,代码是否来自远程机器,会话将丢失,因为它显然基于 cookie 而您没有使用 cookie在fgc中。最好将 curl 与 CURLOPT_COOKIEFILE,CURLOPT_COOKIEJAR 一起使用,它对代码的评估也非常简单。 ob_start(); eval('?>'.$code); $evaled=ob_get_clean();。如果它不是远程的,那么使用included()
  • 使用包含,而不是 file_get_contents。
  • 不,不使用它作为包含。我正在获取由 PHP 脚本生成的 HTML 代码,然后显示它。有点不同。
  • 那么你需要在cURL上使用cookie选项,使用cURL而不是file_get_contents,必要时在PHP脚本之间保留cookie。

标签: php session file-get-contents


【解决方案1】:

如果您访问的文件与调用文件位于同一台服务器上,那么您不妨使用include();,就像@user574632 的答案一样。

但如果没有,要保持会话,您需要处理服务器发送的 cookie;

会话是基于 cookie 的,服务​​器设置会话 cookie,您的浏览器获取它并将其用于所有后续请求。

默认情况下file_get_contents 不会处理 cookie,因此您需要通过访问 $http_response_header 数组从服务器获取标头,然后与正则表达式匹配 Set-Cookie: 标头,然后存储该标头,并在后续请求中使用 cookie 并创建将 cookie 添加到标头并将其传递给 fgc 的流上下文:

<?php 
function get_cookies() {
    //check cookies folder - or make it
    if(!file_exists('./cookies/')){
        mkdir('./cookies/', 0755, true);
    }
    $return = null;
    foreach(glob("./cookies/*.txt") as $file) {
        $return .= file_get_contents($file).';';
    }
    return $return;
}

function save_cookies($http_response_header) {
    print_r($http_response_header);
    foreach($http_response_header as $header) {
        if(substr($header, 0, 10) == 'Set-Cookie'){
            if(preg_match('@Set-Cookie: (([^=]+)=[^;]+)@i', $header, $matches)) {
                $fp = fopen('./cookies/'.$matches[2].'.txt', 'w');
                fwrite($fp, $matches[1]);
                fclose($fp);
            }
        }
    }
}

$opts = array('http' =>
    array('header'=>'Cookie: '.get_cookies()."\r\n")
);

$context  = stream_context_create($opts);
$contents = file_get_contents('http://mywebsite.com/snippets/', false, $context);
save_cookies($http_response_header);

echo $contents;
?> 

或者,您应该使用 curl 来代替它,它更快并且可以很好地处理 cookie。

因此,如下所示,使用 curl,如果 curl 不存在,则恢复为 fgc,所有这些都包含在一个类中的 cookie 支持中,因此包含 3 个函数:

<?php
//example usage
echo new curl_get_contents('http://example.com/page_that_needs_sessions');

class curl_get_contents{
    public $result;

    function __construct($url){
        $this->curl_rev_fgc($url);
    }

    function __toString(){
        return $this->result;
    }

    private function get_cookies() {
        $return = null;

        foreach(glob("./cookies/*.txt") as $file) {
            $return .= file_get_contents($file).';';
        }
        return $return;
    }

    private function save_cookies($http_response_header) {
        foreach($http_response_header as $header) {
            if(substr($header, 0, 10) == 'Set-Cookie'){
                if(preg_match('@Set-Cookie: (([^=]+)=[^;]+)@i', $header, $matches)) {
                    $fp = fopen('./'.$matches[2].'.txt', 'w');
                    fwrite($fp, $matches[1]);
                    fclose($fp);
                }
            }
        }
    }

    private function curl_rev_fgc($url){
        //check cookies folder - or make it
        if(!file_exists('./cookies')){
            mkdir('./cookies/', 0755, true);
        }

        $usragent = 'Mozilla/5.0 (compatible; Yourbot/0.1; +https://yoursite/bot.html)';

        //Check curl is installed or revert to file_get_contents()
        $curl = function_exists('curl_init') ? true : false;

        if($curl){
            $opts = array(
            'http' => array(
            'method' => "GET",
            'header' => 'Cookie: '.$this->get_cookies().'\r\n', // cookie in fgc support
            'user_agent' => $usragent)
            );
            $context = stream_context_create($opts);
            $result  = @file_get_contents($url, false, $context);
            $this->save_cookies($http_response_header);

            if(empty($result)){
                $this->result = 'Error fetching: '.htmlentities($url);
            }else{
                $this->result = $result;
            }
            return;
        }

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($curl, CURLOPT_USERAGENT, $usragent);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        if(!file_exists('./cookies/curl.txt')){
            file_put_contents('./cookies/curl.txt',null);
        }
        curl_setopt($curl, CURLOPT_COOKIEFILE, './cookies/curl.txt');
        curl_setopt($curl, CURLOPT_COOKIEJAR,  './cookies/curl.txt');

        $result = curl_exec($curl);
        if(empty($result)){
            $this->result = 'Error fetching: '.htmlentities($url);
        }else{
            $this->result = $result;
        }
        curl_close($curl);

        return;
    }
}
?>

【讨论】:

  • 感谢接受,我现在正在修复 fgc cookie。
【解决方案2】:

改用包含。如果您需要将输出读入一个变量以便稍后在代码中/其他地方显示,如 cmets 中所建议的,请使用输出缓冲区:

ob_start();
include('path/to/file.php');

$included = ob_get_clean();

//nothing has been output to the browser yet

//later on

echo $included;

【讨论】:

  • 请注意有问题的 远程主机,这只有在您拥有永远不应该打开的 allow_url_include = On 时才有效。
  • @LozCheroneツ 根据最新的 cmets,这些文件不在远程服务器上。
  • 文件在同一个服务器上。当我在问题中说“远程主机”时,这是我的错误。对不起。
猜你喜欢
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 2017-03-19
  • 1970-01-01
  • 2020-01-15
相关资源
最近更新 更多