PHPCMS与CI框架整合(一):实现Session共享

原系统是在PHPCMS基础上进行开发的,应用部署为www.domain.com。中途开发基于CI框架的财务功能,部署为finance.domain.com。为了实现Session共用,需同步两套框架Session体系,即:同样的Session存储介质,同样的Session_id,同样的Session.cookie_domain,功能同样的open ,read ,write ,close ,destory ,gc方法。

限定:本项目Session基于Database驱动。
目标:修改CI系统,与PHPCMS兼容。
步骤:

1、修改config.php文件(位于application/config/config.php)

$config['sess_driver'] = 'database';//修改为数据库驱动
$config['sess_cookie_name'] = 'PHPSESSID';//PHPCMS的存储Session_idCookiename一致
$config['sess_save_path'] = 'XX_session';//PHPCMS用于存储session的表名一致

2、修改Session_database_driver.php(位于system/libraries/Session/drivers/Session_database_driver.php)
IC的db驱动中比PHPCMS多了锁的机制。CI采用数据库字符锁,MySQL下是SELECT GET_LOCK('str',300) / SELECT RELEASE_LOCK
不过我们不用理会,这里主要修改read,write,destory,gc四个方法的CRUD逻辑,并与PHPCMS中的字段一致。

public function read($session_id)
{
    if ($this->_get_lock($session_id) !== FALSE)
    {
        // Prevent previous QB calls from messing with our queries
        $this->_db->reset_query();

        // Needed by write() to detect session_regenerate_id() calls
        $this->_session_id = $session_id;

        $this->_db
            ->select('data')
            ->from($this->_config['save_path'])
            ->where('sessionid', $session_id);

        if ($this->_config['match_ip'])
        {
            $this->_db->where('ip', $_SERVER['REMOTE_ADDR']);
        }

        if (($result = $this->_db->get()->row()) === NULL)
        {
            // PHP7 will reuse the same SessionHandler object after
            // ID regeneration, so we need to explicitly set this to
            // FALSE instead of relying on the default ...
            $this->_row_exists = FALSE;
            $this->_fingerprint = md5('');
            return '';
        }

        // PostgreSQL's variant of a BLOB datatype is Bytea, which is a
        // PITA to work with, so we use base64-encoded data in a TEXT
        // field instead.
        $result = ($this->_platform === 'postgre')
            ? base64_decode(rtrim($result->data))
            : $result->data;

        $this->_fingerprint = md5($result);
        $this->_row_exists = TRUE;
        return $result;
    }

    $this->_fingerprint = md5('');
    return '';
}

public function write($session_id, $session_data)
{
    // Prevent previous QB calls from messing with our queries
    $this->_db->reset_query();
    // Was the ID regenerated?
    if ($session_id !== $this->_session_id)
    {
        if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))
        {
            return $this->_failure;
        }

        $this->_row_exists = FALSE;
        $this->_session_id = $session_id;
    }
    elseif ($this->_lock === FALSE)
    {
        return $this->_failure;
    }

    if ($this->_row_exists === FALSE)
    {

        $insert_data = array(
            'sessionid' => $session_id,
            'ip' => $_SERVER['REMOTE_ADDR'],
            'lastvisit' => time(),
            'userid' => isset($_SESSION['userid']) ? $_SESSION['userid'] : 0,
            //'_userid' => isset($_SESSION['_userid']) ? $_SESSION['_userid'] : 0,
            'roleid' => isset($_SESSION['roleid']) ? $_SESSION['roleid'] : 0,
            'groupid' => isset($_SESSION['groupid']) ? $_SESSION['groupid'] : 0,
            'm' => '',//应该url帮助函数提取片段即目录
            'c' =>  __CLASS__ ,
            'a' =>  __FUNCTION__ ,
            'data' => ($this->_platform === 'postgre' ? base64_encode($session_data) : $session_data)
        );

        if ($this->_db->insert($this->_config['save_path'], $insert_data))
        {
            $this->_fingerprint = md5($session_data);
            $this->_row_exists = TRUE;
            return $this->_success;
        }

        return $this->_failure;
    }

    $this->_db->where('sessionid', $session_id);
    if ($this->_config['match_ip'])
    {
        $this->_db->where('ip', $_SERVER['REMOTE_ADDR']);
    }

    $update_data = array('lastvisit' => time());
    if ($this->_fingerprint !== md5($session_data))
    {
        $update_data['data'] = ($this->_platform === 'postgre')
            ? base64_encode($session_data)
            : $session_data;
    }

    if ($this->_db->update($this->_config['save_path'], $update_data))
    {
        $this->_fingerprint = md5($session_data);
        return $this->_success;
    }

    return $this->_failure;
}
/**
     * Destroy
     *
     * Destroys the current session.
     *
     * @param   string  $session_id    Session ID
     * @return  bool
     */
    public function destroy($session_id)
    {
        if ($this->_lock)
        {
            // Prevent previous QB calls from messing with our queries
            $this->_db->reset_query();

            $this->_db->where('sessionid', $session_id);
            if ($this->_config['match_ip'])
            {
                $this->_db->where('ip', $_SERVER['REMOTE_ADDR']);
            }

            if ( ! $this->_db->delete($this->_config['save_path']))
            {
                return $this->_failure;
            }
        }

        if ($this->close() === $this->_success)
        {
            $this->_cookie_destroy();
            return $this->_success;
        }

        return $this->_failure;
    }

    // ------------------------------------------------------------------------

    /**
     * Garbage Collector
     *
     * Deletes expired sessions
     *
     * @param   int     $maxlifetime   Maximum lifetime of sessions
     * @return  bool
     */
    public function gc($maxlifetime)
    {
        // Prevent previous QB calls from messing with our queries
        $this->_db->reset_query();

        return ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime)))
            ? $this->_success
            : $this->_failure;
    }

3、数据库sessionid字段长度从32改成50。phpcms设置的sessionid字段长度是32,造成CI生成的sessionid长度如果超过32就会被截掉一些。

做完这一切,看起来似乎完工了,试着运行一下
在CI的控制器中插入:

$this->session->set_userdata(array(
            'username'  => 'tangwm',
            'userid'     => '1jcsxdl',
        ));

在PHPCMS系统中输出:

echo $_SESSION['username'];

然并卵,啥也没输出。

4、问题在哪里?
打开debug工具对请求的CI控制器进行监控,发现存储的sessionid的cookie作用域为finance.domain.com,跟踪代码发现
而主站PHPCMS框架中的获取域是www.domain.com
这时需要统一两边用来存储sessionid的cookie作用域,并保证这个cookie作用域设置不会影响其它cookie作用域

CI修改两个地方:
1)、配置文件config.php(位于application/config/config.php)
中加入两个用来存储sessionid的cookies配置(ci原来的是用的统一的cookie设置,这里我做成Session专用的)

$config['sess_cookie_domain'] = '.domain.com';
$config['sess_cookie_path']     = '';

2)、session.php文件
修改protected function _configure(&$params)函数中的这一段:

isset($params['sess_cookie_path']) OR $params['sess_cookie_path'] = config_item('sess_cookie_path');
isset($params['sess_cookie_domain']) OR $params['sess_cookie_domain'] = config_item('sess_cookie_domain');
isset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');

session_set_cookie_params(
    $params['cookie_lifetime'],
    $params['sess_cookie_path'],
    $params['sess_cookie_domain'],
    $params['cookie_secure'],
    TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
);

修改构造函数__construct这一段:

setcookie(
    $this->_config['cookie_name'],
    session_id(),
    (empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime']),
    $this->_config['sess_cookie_path'],
    $this->_config['sess_cookie_domain'],
    $this->_config['cookie_secure'],
    TRUE
);

PHPCMS修改:
在配置文件(caches/configs/system.php)中加上

'session_cookie_domain' => 'nc.com', //session Cookie 作用域

在base.php中加入

ini_set("session.cookie_domain",pc_base::load_config('system','session_cookie_domain'));

对了,这句话加在哪一行?抛硬币决定吧
只要在define(‘IN_PHPCMS’, true);和类定义class pc_base 之间就可以

最后PHPCMS成功输出tangwm。反之在PHPCMS中写入session,CI也能成功读取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值