如何将PHP会话数据保存到数据库而不是文件系统中?

如何将PHP会话数据保存到数据库而不是文件系统中?,第1张

如何将PHP会话数据保存到数据库而不是文件系统中?

在经过数小时的调试过程中,我发现在众多Google搜索中找到的参考文章以及大量的Stack
Overflow答案(例如here,here和here)都提供了无效或过时的信息。

在将会话数据保存到数据库中可能导致[严重]问题的事情:

  • 尽管所有在线示例都说明您可以“填充”

    session_set_save_handler
    ,但没有一个示例说明您也必须设置它
    register_shutdown_function('session_write_close')
    (参考)。

  • 一些(旧的)导游指的是过时的SQL数据库结构,应该 不会 被使用。将会话数据保存到数据库所需的数据库结构是:

    id
    /
    access
    /
    data
    。而已。正如我在一些“指南”和示例中看到的那样,不需要各种额外的时间戳列。

    • 一些较旧的指南也已经过时的MySQL语法,例如
      DELETe * FROM ...
    • 类[我的问题作出]必须 实现
      SessionHandlerInterface
      。我已经看到了指南(上面已引用),这些指南给出的实现方式
      sessionHandler
      不合适。也许以前版本的PHP的方法稍有不同(可能小于5.4)。
  • 会话类方法 必须 返回PHP手册中列出的值。同样,可能是从PHP 5.4之前的版本继承的,但是我阅读的两个指南指出

    class->open
    返回要读取的行,而PHP手册指出需要返回
    true
    false
    仅返回行 。

  • 这是导致我的原始问题的原因 :根据这个非常好的StackOverflow帖子,我使用的是自定义会话名称(实际上,会话名称和会话ID 都是相同的! ),并且生成的会话名称长度为128个字符。由于会话名称是唯一的密钥,需要破解才能破坏会话并接管会话劫持,因此较长的名称/ ID是一件好事。

    • 但是,这引起了一个问题,因为 MySQL默默地 将会话 ID切成 32个字符而不是128个字符,因此它永远无法在数据库中找到会话数据。这是一个完全沉默的问题(可能是由于我的数据库连接类未引发此类警告)。但这是要提防的。如果从数据库检索会话有任何问题,请首先检查 完整的 会话ID是否可以存储在提供的字段中。

因此,除了所有这些之外,还需要添加一些额外的细节:

PHP手册页(上面链接)显示了一个类对象不合适的行:

$handler = new MySessionHandler();session_set_save_handler($handler, true);session_start();

如果将其放在类构造函数中,效果也一样:

class MySessionHandler implements SessionHandlerInterface {    private $database = null;public function __construct(){    $this->database = new Database(whatever);    // Set handler to overide SESSION    session_set_save_handler(        array($this, "open"),        array($this, "close"),        array($this, "read"),        array($this, "write"),        array($this, "destroy"),        array($this, "gc")        );    register_shutdown_function('session_write_close');    session_start();    }...}

意味着要在输出页面上开始会话,您需要做的是:

<?phprequire "path/to/sessionhandler.class.php"; new MySessionHandler();//Bang session has been setup and started and works

作为参考,完整的Session通信类如下所示,该类可与PHP 5.6一起使用(可能是7,但尚未在7上进行测试)

<?phpclass MySessionHandler implements SessionHandlerInterface {    private $database = null;    public function __construct($sessionDBconnectionUrl){         require_once "class.database.include.php"; $this->database = new DatabaseObject($sessionDBconnectionUrl);        // Set handler to overide SESSION        session_set_save_handler( array($this, "open"), array($this, "close"), array($this, "read"), array($this, "write"), array($this, "destroy"), array($this, "gc")        );        register_shutdown_function('session_write_close');        session_start();    }        public function open($savepath, $id){        // If successful        $this->database->getSelect("SELECT `data` FROM sessions WHERe id = ? LIMIT 1",$id,TRUE);        if($this->database->selectRowsFoundCounter() == 1){ // Return True return true;        }        // Return False        return false;    }        public function read($id)    {        // Set query        $readRow = $this->database->getSelect('SELECT `data` FROM sessions WHERe id = ? LIMIT 1', $id,TRUE);        if ($this->database->selectRowsFoundCounter() > 0) { return $readRow['data'];        } else { return '';        }    }        public function write($id, $data)    {        // Create time stamp        $access = time();        // Set query        $dataReplace[0] = $id;        $dataReplace[1] = $access;        $dataReplace[2] = $data;        if ($this->database->noReturnQuery('REPLACE INTO sessions(id,access,`data`) VALUES (?, ?, ?)', $dataReplace)) { return true;        } else { return false;        }    }        public function destroy($id)    {        // Set query        if ($this->database->noReturnQuery('DELETE FROM sessions WHERe id = ? LIMIT 1', $id)) { return true;        } else { return false;        }    }        public function close(){        // Close the database connection        if($this->database->dbilink->close){ // Return True return true;        }        // Return False        return false;    }        public function gc($max)    {        // Calculate what is to be deemed old        $old = time() - $max;        if ($this->database->noReturnQuery('DELETe FROM sessions WHERe access < ?', $old)) { return true;        } else { return false;        }    }    public function __destruct()    {        $this->close();    }}

用法:如类代码文本上方所示。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5052792.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存