最近了学习了一下 php session 中 配置 以及重写 session的方法

session 中有几个比较重要内容

  • 传送会话ID

  有两种方式用来传送会话 ID:

    Cookies

    URL 参数

  会话模块支持这两种方式。 Cookie 方式相对好一些,但是用户可能在浏览器中关闭 Cookie,所以 第二种方案就是把会话 ID 直接并入到 URL 中,以保证会话 ID 的传送。无需开发人员干预,PHP 就可以自动处理 URL 传送会话 ID 的场景。 如果启用了

  session.use_trans_sid 选项, PHP 将会自动在相对 URI 中包含会话 ID。

  • 为什么使用 session 与 cookie

        HTTP是无连接的,所以需要Cookie来进行用户和连接信息的记录 ,利用cookie就可以跟踪用户了 ,但cookie是存在于客户端 ,是不安全的 , 所以要引入session ,session 是存在于服务器端的 ,我们把一些重要的数据保存于session之中 ,然后在cookie中保

        留一 个sessionid ,这样既可以让服务器识别用户的信息又增加了数据的安全性。

  • session 的生命周期

当客户端发送一次请求时程序会自动生成一个sessionid 这个 sessionid 会被保存到全局数组cookie中 ,一般默认情况下 这个保存sessionid 的键值为 PHPSESSID , 然后系统会在服务器中生成一个 以sessionid 命名的文件保存超全局变量$_SESSION 中的数据

(php.ini session.save_handle = files 的情况下),当下一次用户请求的时候系统就会根据 $_COOKIE['PHPSESSID'] 中的值 ,到服务器中查找对应的文件,读取对应的数据返回到客户端

php.ini 配置文件

session.save_path: 设置session在服务器中的保存路径

session.name : 设置cookie 中 保存sessionid 的键名 默认为 PHPSESSID

session.save_handle : 设置session 的管理器 可选 文件保存(files) ,用户自定义(user),redis 等

session.auto_start:自动开启session 默认关闭

session.serialize_handle: 序列化$_SESSION 可选 php(默认) , php_serialize(php 内置函数 serialize() , unserialize() 序列化 推荐)  ,php_binary 和 WDDX

session.gc_maxlifetime:设置过期时间 默认 1440 s

session.use_cookie: 使用cookie 传递 sessionid 默认开启

session.use_only_cookie : 只能使用cookie 传递 sessionid

session.cookie_httponly : 只能使用http 协议传递的cookie ,不能使用js 中的cookie 防止 xss 攻击

 

自定义实现session 管理器 (mysql 存储)

数据库结构 :创建数据库 ql_2017 , 建立表单:session_data(id , session_id , session_data , expre)

CREATE TABLE `session_data` (
  `id` bigint(11) NOT NULL,
  `session_id` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
  `session_data` varchar(255) CHARACTER SET latin1 NOT NULL DEFAULT '',
  `expre` int(11) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

 

 

Model.php

//简单实现 mysql 的 单例模式
class Model{
    private $host = 'localhost';
    private $user = 'root';
    private $pwd  = '';
    private $port = '3306';
    private $db   = 'ql_2017';
    private static $_link = null;
    private $err = '';
    
    
    
    private function __construct(){
       
       $mysql = $this -> connection();
       if($mysql === false) exit($mysql);
       self::$_link = $mysql;
        
    }
        
    protected function connection(){
        
        try{
            $mysql = new \mysqli();
        }catch(\Exception $e){
            $this -> err = $mysql -> error;
        }
       
        if($mysql -> errno) return false;
        
        try{
            $mysql -> connect($this -> host , $this -> user , $this -> pwd , $this -> db);
        }catch(\Exception $e){
            $this -> err = $mysql -> connect_error;
        }
        if($mysql -> connect_errno) return false;

        $mysql -> set_charset('utf8');
       
        return $mysql;
    }
    
    public static function getInstantce(){
        if(self::$_link === null) new Model();
        return self::$_link;
    }
}

ReWriteSession.php

<?php
spl_autoload_register(function($class){
    str_replace('/', '\\', $class);
    include $class.'.php';
});
    //继承 php内置接口  SessionHandlerInterface 实现 open() ,read() ,write() , gc() , destory() 方法 
class ReWriteSession implements SessionHandlerInterface{
    
    private $_link = null;
    private $expremc = 'session_expre';
    
    public function open( $save_path,  $session_name)
    {
       echo 'open session <br>';
     
       $this ->_link = Model::getInstantce();
      
       return true;

    }
    
    public function read($session_id)
    {
        
        echo 'read session <br>';
        $sql = "select session_data , expre from session_data where session_id = '$session_id' and expre > ".time();
        //$sql = "select session_data , expre from session_data where session_id = '$session_id'";
        $result = $this -> _link -> query($sql);
       
        $arr_data = array();
        while($row = $result -> fetch_assoc()){
            $arr_data[] = $row;
        }
        
        //$this -> _link = $result;
        if(count($arr_data) > 0){
            
            $expre = $arr_data[0]['expre'];
            $data = $arr_data[0]['session_data'];
           
        }else{
            $expremc = $this -> expremc;
            $expre = isset($_COOKIE[$expremc]) ? $_COOKIE[$expremc] : time()+ini_get('session.gc_maxlifetime');
            $data = '';
        }
            
        setcookie($this -> expremc , $expre);
        return $data;
    }

    public function destroy( $session_id)
    {
        echo 'destroy session <br>';
        $sql = 'delete from session_data where session_id <= '.$session_id;
        try{
            $res = query($sql);
        }catch(\Exception $e){
            $res = false;
        }
        
        if($res === false) return false;
        //$this -> _link = $res;
        return true;
        
    }

    public function gc( $maxlifetime)
    {
        echo 'gc session '.$maxlifetime.' <br>';
        $sql = 'delete from session_data where expre <= '.time();
        try{
            $res = $this ->_link -> query($sql);
        }catch(\Exception $e){
            $res = false;
        }
        
        if($res === false) return false;
        return true;
    }

    public function close()
    {
        echo 'colse session <br>';
       return true;
    }

    public function write( $session_id,  $session_data)
    {   
        $arr_data = unserialize($session_data);
        if(!is_array($arr_data)) return false;
        if(count($arr_data) === 0) return true;
        echo "write session <pre>"; print_r($arr_data); 
        $expre = isset($_COOKIE['session_expre']) ? $_COOKIE['session_expre'] : ini_get('session.gc_maxlifetime')+time();
    
       $sql = "replace into session_data(`session_id` ,`session_data` ,`expre`) values('$session_id' ,'$session_data' , $expre )";

       try{
           $res = $this ->_link -> query($sql);
       }catch(\Exception $e){
           $res = false;
       }

       if($res === false) return false;
 
       return true;
      
    }

 

}

OtherPage.php

spl_autoload_register(function($class){
    str_replace('/', '\\', $class);
    include $class.'.php'; 
});

ini_set("session.save_handler" , "user");
$handle = new ReWriteSession();
session_set_save_handler($handle);
session_start();
echo '你好,你好 !你的session 存储信息为:';
echo '<pre>'; print_r($_SESSION);
echo '<br>你的sessionid为 :' . session_id().'<br>';

 

测试页面:

<?php
spl_autoload_register(function($class){
    str_replace('/', '\\', $class);
    include $class.'.php'; // / -> \
});



if(!isset($_COOKIE['session_expre'])) setcookie('session_expre' , time()+3600);
ini_set("session.save_handler" , "user");
$handle = new ReWriteSession();
session_set_save_handler($handle);
session_start();

$sname = ini_get('session.name');
$sid   = session_id();
if(!isset($_COOKIE[$sname])) setcookie($sname  , $sid , time()+3600 );
$_SESSION['food'] = 'banana';
$_SESSION['animal'] = 'lion';

echo '<a href= "OtherPage.php" target="_blank">cleck me !</a><br>';