php - 我应该如何在 PHP 中实现延迟 session 创建?

标签 php session

默认情况下,PHP 的 session 处理机制会设置 session cookie header 并存储 session ,即使 session 中没有数据也是如此。如果 session 中没有设置数据,那么我不希望在响应中将 Set-Cookie header 发送到客户端,并且我不希望在服务器上存储空 session 记录。如果数据添加到 $_SESSION,则正常行为应该继续。

我的目标是实现 Drupal 7 和 Pressflow 那种延迟 session 创建行为。除非在应用程序执行期间将数据添加到 $_SESSION 数组,否则不会存储 session (或发送 session cookie header )。此行为的要点是允许反向代理,例如 Varnish缓存和服务匿名流量,同时让经过身份验证的请求传递到 Apache/PHP。 Varnish(或另一个代理服务器)被配置为传递任何没有 cookie 的请求,正确地假设如果 cookie 存在,则该请求是针对特定客户端的。

我已从 Pressflow 移植了 session 处理代码,该代码使用 session_set_save_handler() 并覆盖 session_write() 的实现来检查 $_SESSION 中的数据 数组,然后保存,并将其写为库,并在此处添加答案(如果这是最佳/唯一的路线)。

我的问题:虽然我可以实现完全自定义的session_set_save_handler()系统,但是否有一种更简单的方法可以以相对通用的方式获得这种惰性 session 创建行为,对于大多数应用程序来说是透明吗?

最佳答案

嗯,一种选择是使用 session 类来启动/停止/存储 session 中的数据。所以,你可以这样做:

class Session implements ArrayAccess {
    protected $closed = false;
    protected $data = array();
    protected $name = 'mySessionName';
    protected $started = false;

    protected function __construct() {
        if (isset($_COOKIE[$this->name])) $this->start();
        $this->data = $_SESSION;
    }

    public static function initialize() {
        if (is_object($_SESSION)) return $_SESSION;
        $_SESSION = new Session();
        register_shutdown_function(array($_SESSION, 'close'));
        return $_SESSION;
    }

    public function close() {
        if ($this->closed) return false;
        if (!$this->started) {
            $_SESSION = array();
        } else {
            $_SESSION = $this->data;
        }
        session_write_close();
        $this->started = false;
        $this->closed = true;
    }

    public function offsetExists($offset) { 
        return isset($this->data[$offset]); 
    }

    public function offsetGet($offset) {
        if (!isset($this->data[$offset])) {
            throw new OutOfBoundsException('Key does not exist');
        }
        return $this->data[$offset]; 
    }

    public function offsetSet($offset, $value) {
        $this->set($offset, $value);
    }

    public function offsetUnset($offset) {
        if (isset($this->data[$offset])) unset($this->data[$offset]);
    }

    public function set($key, $value) {
        if (!$this->started) $this->start();
        $this->data[$key] = $value;
    }

    public function start() {
        session_name($this->name);
        session_start();
        $this->started = true;
    }
}

要使用,请在脚本开始时调用 Session::initialize()。它将用对象替换 $_SESSION ,并设置延迟加载。之后,你就可以这样做

$_SESSION['user_id'] = 1;

如果 session 未启动,它将启动,并且 user_id 键将设置为 1。如果您在任何时候想要关闭(提交) session ,只需调用 $_SESSION->close( )

您可能想要添加一些更多的 session 管理功能(例如 destroy、regenerate_id、更改 session 名称的能力等),但这应该实现您想要的基本功能...

它不是一个 save_handler,它只是一个管理 session 的类。如果您确实愿意,您可以在类中实现 ArrayAccess,并在构造时将 $_SESSION 替换为该类(这样做的好处是,遗留代码仍然可以像以前一样使用 session ,而无需调用 $session ->setData())。唯一的缺点是我不确定 PHP 使用的序列化例程是否可以正常工作(您需要在某个时候将数组放回到 $_SESSION 中......可能使用 register_shutdown_function()...

关于php - 我应该如何在 PHP 中实现延迟 session 创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2998166/

相关文章:

php - 从 MySql 数据库中获取值到表单中

session - Magento 自定义添加到购物车流程不起作用

Internet Explorer 中的 PHP session 数据更改

c# - session 是否使用 cookie?

php - SQL QUERY 在 WHERE 语句中使用 OR 返回所有结果

php - 使用多个 php 函数查询单个(mysql)数据库的正确方法

javascript - 单击时如何将 div 的 id 传递到另一个 php 页面

django - 使用 session 来存储权限信息是否安全

node.js - 能够为每个BrowserWindow对象创建一个新 session ?

php - 未添加 Laravel 5 表单选择 ID 属性