最近了学习了一下 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>';