为什么要进行session共享?

因为一些大型网站,通常会有很多服务器,每个服务器运行不同的业务模块,并使用二级域名(或是完全不同的域名),而用户系统是统一的,通过登陆名、密码来登陆各模块。用户数据放在指定的数据库中,各模块都可访问。问题是,当用户登陆模块A时,再进入模块B时,模块B无法获取用户在模块A登陆时的session数据,那么用户又要在模块B重新登陆一次。所以就要用到了sesson共享。
 
php中session默认是保存在文件中的,在php.ini
session.save_handler = files
我们通过下面的函数来自定义session的存储
session_set_save_handler
该函数有七个参数,分别如下:
open(string $savePath, string $sessionName)
自动会话开始或手动调用session_start()后第一个被调用回调函数

close()
write回调函数调用之后调用

read(string $sessionId)
读取会话数据,如果没有则返回空字符串

write(string $sessionId, string $data)
保存会话数据

destroy($sessionId)
删除会话数据

gc($lifetime)
PHP会不时的调用该函数进行垃圾收集, 调用周期由session.gc_probability和session.gc_divisor参数控制。
lifetime参数由session.gc_maxlifetime设置。

create_sid()
创建新的会话id
我们创建数据表来存储session数据
CREATE TABLE `session` (
`sid` varchar(32) NOT NULL DEFAULT '' COMMENT 'session_id',
`expire` int(11) NOT NULL COMMENT '过期时间',
`data` text COMMENT 'session数据',
PRIMARY KEY (`sid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='session表';
<?php
class DBSession {
    protected $db = null;
    protected $lifeTime = 0;
    protected $sessTable = '';

    public function __construct($db, $sessTable) {
        $this->db = $db;
        $this->sessTable = $sessTable;
        $this->lifeTime = ini_get('session.gc_maxlifetime');

        ini_set('session.save_handler', 'user');
        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');
    }

    public function open($savePath, $sessName) {
        return true;
    }

    public function close() {
        $this->gc($this->lifeTime); 
        return true;
    }

    public function read($sessId) {
        $time = time();
        $ret = mysql_query("SELECT `data` FROM `{$this->sessTable}` WHERE `sid`='{$sessId}' AND `expire` > {$time};", $this->db);
        if($ret) {
           $row = mysql_fetch_assoc($ret);
           return $row['data']; 
        }
        return ''; 
    }

    public function write($sessId, $sessData) {
        $expire = time() + $this->lifeTime;
        $sessData = mysql_real_escape_string($sessData);
        
        $ret = mysql_query("SELECT COUNT(*) AS cnt FROM `{$this->sessTable}` WHERE `sid`='{$sessId}';", $this->db);
        $row = mysql_fetch_assoc($ret);
        if($row['cnt']) {
            $sql = "UPDATE `{$this->sessTable}` SET `data`='{$sessData}', `expire`={$expire} WHERE `sid`='{$sessId}';";
        } else {
            $sql = "INSERT INTO `{$this->sessTable}` (`sid`,`expire`,`data`) VALUES('{$sessId}',{$expire},'{$sessData}');";
        }
        mysql_query($sql, $this->db);
        if(mysql_affected_rows($this->db)) {
            return true;
        }
        return false;
    }

    public function destroy($sessId) {
        mysql_query("DELETE FROM `{$this->sessTable}` WHERE `sid`='{$sessId}';", $this->db); 
        if(mysql_affected_rows($this->db)) {
            return true;
        }
        return false;
    }

    public function gc($lifeTime) {
        $time = time();
        mysql_query("DELETE FROM `{$this->sessTable}` WHERE `expire` < {$time};", $this->db); 
        return mysql_affected_rows($this->db);
    }
}

$sessDb = mysql_connect('127.0.0.1', 'root', '') or die('connect error');
mysql_select_db('test', $sessDb) or ('select db error');
mysql_query('set names utf8', $sessDb);
new DBSession($sessDb, 'session');
session_start();
我们通过函数session_set_save_handler来自定义会话的存储方式。
我们创建三个虚拟主机分别为
www.a.com
www.b.com
www.c.com
分别在三个虚拟主机下创建index.php,来设置会话数据。
<?php
require './DBSession.php';

$_SESSION['userinfo'] = array(
    'name' => 'aaa',
);

var_dump($_SESSION['userinfo']);
查看session数据表如下:
php SESSON共享 (mysql方式) - 怀素真 - 因上努力 果上随缘
 可以看到a,b ,c三个站的会话信息全部保存在了session表中了,只要拿到了session_id就可以共享的访问其他站设置的会话数据。
posted on 2017-01-26 21:02  怀素真  阅读(376)  评论(0编辑  收藏  举报