周梦康 发表于 2014-07-16 4235 次浏览 标签 : ThinkPHP

ThinkPHP3.1.3版本中\ThinkPHP3.1.3\Extend\Driver\Session\SessionDb.class.php

ThinkPHP3.2.2版本中\ThinkPHP3.2.2\ThinkPHP\Library\Think\Session\Driver\Db.class.php

代码地址:https://github.com/liu21st/thinkphp/blob/master/ThinkPHP/Library/Think/Session/Driver/Db.class.php

变动不大,只不过在3.2.2版本中去掉了execute方法(原来session_set_save_handler是封装在execute方法里的),而是直接在session函数(\ThinkPHP3.2.2\ThinkPHP\Common\functions.php)里调用函数session_set_save_handler来调用我们的 session 分布式存储的驱动类,之所以这样做是因为之前只写了一个数据库版本的,而现在又增加了一个memcache版本的,所以提出来公用了。

这里最重要的就是session_set_save_handler这个函数,提供了session的自定义存储方法,存储不仅仅是简单的存和取了,还有销毁,垃圾回收。这样就可以保证,比如session过期的情况下,数据库对应的那条数据也会被删掉。具体查看手册,手册里说的很详细。

下面以新版本的为例:

if(C('SESSION_TYPE')) { // 读取session驱动
    $type   =   C('SESSION_TYPE');
    $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
    $hander =   new $class();
    session_set_save_handler(
        array(&$hander,"open"), 
        array(&$hander,"close"), 
        array(&$hander,"read"), 
        array(&$hander,"write"), 
        array(&$hander,"destroy"), 
        array(&$hander,"gc")); 
}
// 启动session
if(C('SESSION_AUTO_START'))  session_start();

而且在Db驱动类里面做了分布式,读写分离等处理机制。(需要配合默认的配置文件\thinkphp_3.2.2\ThinkPHP\Conf\convention.php一起查看)

    /**
     * 打开Session 
     * @access public 
     * @param string $savePath 
     * @param mixed $sessName  
     */
    public function open($savePath, $sessName) { 
       $this->lifeTime = C('SESSION_EXPIRE')?C('SESSION_EXPIRE'):ini_get('session.gc_maxlifetime');
       $this->sessionTable  =   C('SESSION_TABLE')?C('SESSION_TABLE'):C("DB_PREFIX")."session";
       //分布式数据库
       $host = explode(',',C('DB_HOST'));
       $port = explode(',',C('DB_PORT'));
       $name = explode(',',C('DB_NAME'));
       $user = explode(',',C('DB_USER'));
       $pwd  = explode(',',C('DB_PWD'));
       if(1 == C('DB_DEPLOY_TYPE')){
           //读写分离
           if(C('DB_RW_SEPARATE')){
               $w = floor(mt_rand(0,C('DB_MASTER_NUM')-1));
               if(is_numeric(C('DB_SLAVE_NO'))){//指定服务器读
                   $r = C('DB_SLAVE_NO');
               }else{
                   $r = floor(mt_rand(C('DB_MASTER_NUM'),count($host)-1));
               }
               //主数据库链接
               $hander = mysql_connect(
                   $host[$w].(isset($port[$w])?':'.$port[$w]:':'.$port[0]),
                   isset($user[$w])?$user[$w]:$user[0],
                   isset($pwd[$w])?$pwd[$w]:$pwd[0]
                   );
               $dbSel = mysql_select_db(
                   isset($name[$w])?$name[$w]:$name[0]
                   ,$hander);
               if(!$hander || !$dbSel)
                   return false;
               $this->hander[0] = $hander;
               //从数据库链接
               $hander = mysql_connect(
                   $host[$r].(isset($port[$r])?':'.$port[$r]:':'.$port[0]),
                   isset($user[$r])?$user[$r]:$user[0],
                   isset($pwd[$r])?$pwd[$r]:$pwd[0]
                   );
               $dbSel = mysql_select_db(
                   isset($name[$r])?$name[$r]:$name[0]
                   ,$hander);
               if(!$hander || !$dbSel)
                   return false;
               $this->hander[1] = $hander;
               return true;
           }
       }
       //从数据库链接
       $r = floor(mt_rand(0,count($host)-1));
       $hander = mysql_connect(
           $host[$r].(isset($port[$r])?':'.$port[$r]:':'.$port[0]),
           isset($user[$r])?$user[$r]:$user[0],
           isset($pwd[$r])?$pwd[$r]:$pwd[0]
           );
       $dbSel = mysql_select_db(
           isset($name[$r])?$name[$r]:$name[0]
           ,$hander);
       if(!$hander || !$dbSel) 
           return false; 
       $this->hander = $hander; 
       return true; 
    }

关于整个Session驱动的内容我就不复制了,可以看上面我复制的那个地址,我个人的理解就是在主库上写session的时候,将数据写入数据库,然后同步的从库,之后就不走session了,而是走数据库,用到仅仅是一个sessionId,通过sessionId去数据库里查询,取出数据。

我们都说session是相对来说比较安全的,但是毕竟这个sessionID还是存放在cookie里的,假设我复制别人的cookie里的sessionId,这样岂不是能获取到session了?关于这个解释:http://zhoumengkang.com/326.html

👇 下面是我的公众号,高质量的博文我会第一时间同步到公众号,给个关注吧!

评论列表