【问题标题】:How do I set the session cookie path in cakePHP while still saving session data in the database?如何在 cakePHP 中设置会话 cookie 路径,同时仍将会话数据保存在数据库中?
【发布时间】:2011-11-08 00:25:04
【问题描述】:

默认情况下,cakePHP 将会话 cookie 放在应用程序级别。例如,如果您在 www.mydomain.com/myapp 有一个 cakePHP 应用程序,则 cookie 存储在“/myapp”中。 我需要我的会话数据可供 www.mydomain.com 上的其他应用程序使用,因此我希望将会话 cookie 存储在“/”中。

我找到了一堆关于如何做到这一点的文章,但是当使用这两个热门帖子/指南中解释的方法时,它会禁用将会话保存在数据库中。

How to bend CakePHP's session handling to your needs

cakePHP - Cookbook - Sessions

有谁知道如何将会话 cookie 路径更改为“/”,同时仍然能够将会话数据保存在数据库中?

谢谢!

【问题讨论】:

  • 澄清一下,cakePHP 已经可以将会话数据保存在数据库中。但是,当它这样做时(默认情况下),它会在应用程序目录级别设置会话 cookie 路径,这不是我想要的。我想要它在网络根级别。
  • 感谢大家的意见,但不幸的是我无法得到我正在寻找的答案。在这个时间点,我在核心 cake_session.php 文件中做了一行小的修改,修复了这个问题。这完全是一种 hack,我讨厌我不得不那样做,但它确实有效。如果有人看到一种无需重写 cakePHP 代码且无需破解其核心文件的方法,我很想知道。

标签: php session cakephp session-cookies


【解决方案1】:

这不能在 PHP 级别而不是在 CakePHP 本身中完成吗?

所以你可以使用session_set_save_handler() (man page)以如下几种方式来实现会话存储在数据库中。以下代码来自对PHPmanual page by maria at junkies dot jp的评论,我没有专门测试过:

<?php
class Session
{

    /**
     * a database connection resource
     * @var resource
     */
    private $_sess_db;

    /**
     * Open the session
     * @return bool
     */
    public function open() {

        if ($this->_sess_db = mysql_connect(SESSION_DB_HOST,
                                            SESSION_DB_USER,
                                            SESSION_DB_PASS)) {
            return mysql_select_db(SESSION_DB_DATABASE, $this->_sess_db);
        }
        return false;

    }

    /**
     * Close the session
     * @return bool
     */
    public function close() {

        return mysql_close($this->_sess_db);

    }

    /**
     * Close the session
     * @return bool
     */
    public function close() {

        return mysql_close($this->_sess_db);

    }

    /**
     * Read the session
     * @param int session id
     * @return string string of the sessoin
     */
    public function read($id) {

        $id = mysql_real_escape_string($id);
        $sql = sprintf("SELECT `data` FROM `sessions` " .
                       "WHERE id = '%s'", $id);
        if ($result = mysql_query($sql, $this->_sess_db)) {
            if (mysql_num_rows($result)) {
                $record = mysql_fetch_assoc($result);
                return $record['data'];
            }
        }
        return '';

    }

    /**
     * Write the session
     * @param int session id
     * @param string data of the session
     */
    public function write($id, $data) {

        $sql = sprintf("REPLACE INTO `sessions` VALUES('%s', '%s', '%s')",
                       mysql_real_escape_string($id),
                       mysql_real_escape_string($data),
                       mysql_real_escape_string(time()));
        return mysql_query($sql, $this->_sess_db);

    }

    /**
     * Destoroy the session
     * @param int session id
     * @return bool
     */
    public function destroy($id) {

        $sql = sprintf("DELETE FROM `sessions` WHERE `id` = '%s'", $id);
        return mysql_query($sql, $this->_sess_db);

}

    /**
     * Garbage Collector
     * @param int life time (sec.)
     * @return bool
     * @see session.gc_divisor      100
     * @see session.gc_maxlifetime 1440
     * @see session.gc_probability    1
     * @usage execution rate 1/100
     *        (session.gc_probability/session.gc_divisor)
     */
    public function gc($max) {

        $sql = sprintf("DELETE FROM `sessions` WHERE `timestamp` < '%s'",
                       mysql_real_escape_string(time() - $max));
        return mysql_query($sql, $this->_sess_db);

    }

}

//ini_set('session.gc_probability', 50);
ini_set('session.save_handler', 'user');

$session = new Session();
session_set_save_handler(array($session, 'open'),
                         array($session, 'close'),
                         array($session, 'read'),
                         array($session, 'write'),
                         array($session, 'destroy'),
                         array($session, 'gc'));

// below sample main

session_start();
session_regenerate_id(true);

?>

所以你可以在你的引导文件中引用它。

【讨论】:

  • 这基本上是 cakePHP 已经在做的,所以我不想重做。我只是希望有一种方法可以覆盖他们的 session.cookie_path ini 设置,而无需破解他们的核心代码,并且仍然将数据保存在数据库中。在 cakePHP 中,您可以在核心配置中设置自定义会话处理,我尝试了与您发布的内容非常相似的内容,同时尝试利用 cakePHP 已经为所有这些功能提供的功能,但没有成功。我仍然没有放弃这个想法,我只是不想返工他们已经可以正常工作的功能。
【解决方案2】:

基本上,普通服务器中的会话默认应该是全局的。至少在我使用过的所有服务器中都有。所以我实际上会在脚本中进行一些核心解决方法之前更改我的服务器。

但是,如果您使用的是一些与会话相关的类,最后有 __destruct() 函数..在其中,您有 session_destroy(); 或者它并不重要,session_destroy();坐,但这对您的路径相关问题确实很重要。我运行了一些快速测试,默认情况下会话在域内是全局的......但是,在第二页上,如果触发页面将其杀死,显然不会显示该变量。

我的测试:

trigger.php 文件:

<?

session_start();

echo $_SESSION['foo'] = 'bar';

// session_destroy(); <- This kills it
// Otherwise $_SESSION['foo'] gets displayed on the child.php file in test/ directory

?>

test/child.php 文件:

<?

session_start();

echo $_SESSION['foo'];

?>

【讨论】:

  • 我说的是会话。我的问题与 setcookie 函数无关。在 PHP 中处理会话时,会保存一个包含会话 ID 的 cookie,这样当用户在您网站上的页面之间移动时,它可以提取正确的会话数据。
  • 从技术上讲,它的会话应该在域中是全局的。我从来没有真正关注过它。
  • 我改变了我的答案,但我不确定我是否理解你的正确。如果我错了,请纠正我。
  • 会话范围在 PHP ini 中定义,默认设置为全局,示例配置:; The path for which the cookie is valid. session.cookie_path = / cakePHP,不幸的是,使用 ini_set 函数编辑 ini 设置
  • 好的,但是你为什么要使用那个框架呢?创建一个使用附加 DB 类进行 sql 连接的 UI 类非常容易。你不能编辑 cakePHP 核心,它不会编辑你的 ini_set 函数。..?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
  • 2014-12-30
相关资源
最近更新 更多