session
理解:
session
会话数据的存储位置:服务器端。- 实现方式:
2.1 在 服务器端,建立很多的会话数据区(session
数据区)
2.2 为 每个session
会话数据区分配唯一标识
2.3 将该唯一标识,分配给对应会话浏览器(因此:session
技术基于COOKIE
技术!)
操作步骤:
1、开启session机制
session_start();//开启后,会生成一个独立的session_id,用于后期与该浏览器建立通信。
2、操作session数据
session_start();//开启session机制
$_SESSION['name'] = 'hello';//添加
$_SESSION['name'] = 'world';//修改
var_dump($_SESSION['name']);//获取
unset($_SESSION['name']);//删除
浏览器端存储session_id
- 是一个普通的
cookie
变量,变量名:PHPSESSID
。 - 两种情况:
2.1 浏览器没有session_id
时:浏览器请求服务器端,服务器php开启了session机制
,PHP就会生成一个session_id
,以cookie的形式设置在浏览器端:
2.2 浏览器存在session_id
时:浏览器请求服务器端,服务器php开启了session机制
,PHP不会生成一个session_id
。
服务器端session会话数据区
- 默认,每个
session
会话数据区,就是一个独立的文件。存储于 服务器所在操作系统的临时目录中 - 如果有多个会话,则会出现多个不同
session_id
为文件名的文件
语法问题
1、多数据类型的支持:
- PHP内部存储机制会先将各种类型的session变量通过serialize()先进行序列化操作,然后再存储在以session_id为名称的文件名中,(同理:程序获取session变量之前,PHP会自动使用unserialize()进行反序列化操作)
- 在session中存储对象时,获取该对象时,需要找到对象对应的类(要提前加载进来)
2、开启session
自动开启:
1 . 配置php.ini文件中的参数session.atuo_start = 1
2 . 使用函数ini_set('session.auto_start',1)
重复开启
1:session不能重复开启。一旦重复开启,后边的开启会被忽略!但是,会触发一个notice
级别的错误。
2:通常的解决方案,开启session时,增加@,错误屏蔽!
session_start();
@session_start();
3、session属性
- 理解:
1:因为cookie
中存储session_id
值,决定了对应的session
数据的属性。所以cookie中的数据属性与session
的一致。
2:通过设置cookie
中session_id
这个cookie
变量属性来改变session数据的属性
方法一 :配置php.ini中
sessio.cookie_*
变量(例如:session.cookie_lifetime=0
)
方法二 :在开启session
之前使用ini_set()
用于设置某个PHP配置选项
方法三 :在开启session
之前使用函数session_set_cookie_params(有效期,有效路径,有效域,是否仅安全连接传输,是否HTTPONLY)
—————–(建议使用后两种,因为只会对当前文件产生影响)
4、session数据区的操作
只有开启session机制,才能够访问session数据区,对其进行操作
5、重写session的存储机制
理解:
1:session
数据区默认以 文件的形式存储在服务器操作系统临时目录中
2:当session
数据区过多时,文件形式的存储,操作速度变慢。磁盘的读写(IO
,input/output)开销是很大的。
3:实际项目中,都会采用其他的方式更快地存储session
数据。典型的办法:数据库(mysql
),内存(redis、memcache
)。步骤:
- 步骤 1: 通过以下这个函数告知session机制,在需要读写时,使用用户自定义的读写函数完成。
session_set_save_handler(
开始函数,结束函数,读函数,写函数,删除函数,GC函数
);
//用来将用户自定义的函数,设置成session存储相关的函数。
注意:以上的语法,仅仅是设置告知,不是调用以上6个函数,这六个函数,在session机制运行到某个时间点时,才会被调用!
- 步骤二 :如何设置这些函数
读函数:
1:读取和返回session数据
2:接受传递的session_id 参数(用来识别对应的数据区)
3:如果没有读取到,返回空字符串即可
function sessRead($sid){//对应2
$sql = "SELECT sess_data FROM session WHERE id = $sid "
$row = $DB->query($sql,'One');//对应1
if($row){
return $row;//返回数据
}else{
return "";//对应3
}
}
写函数:
1 . 接受session_id和 需要写入的内容(serialize序列化好的)两个参数
2 . 将数据存储起来
function sessWrite($sid,$sess_str){
$sql = "replace into session values('$sid','$sess_str')";
return $DB->exec($sql);
}
删除操作:
1 . 接受session_id参数
2 . 销毁session
,删除对应的session
数据区,同时关闭session
机制
function sessDelete($sid){
$sql = "delete from session where sid = '$sid'";
return $DB->exec($sql);
}
垃圾回收操作:
1 . 删除服务器上过时的session数据
- 垃圾判断:
1:设定一个有效期(默认是在php.ini
中设置session.gc_maxlifetime=1440
)
2 :记录最后一次写入的时间
3 :如果当前时间减去最后一次写入时间大于有效期时间,则为垃圾
解决方案:
1 . 在session表添加一个字段用来存储最后写入时间
2 . 通过当前时间-写入时间 > 有效期
来判断是否为垃圾
- 垃圾删除
1 . 在session_start()
过程中,开启session
机制过程中,有几率地执行垃圾回收操作。(几率 = session.gc_probability 除以 session.gc_divisor
,所以可以通过设置这两个参数来改变几率)
2 . 接收一个有效期参数(session.gc_maxlifetime)
3 . 一旦执行,就会删除所有的过期的垃圾数据区。
function sessionGC($maxlifetime){
$sql = "DELETE FROM session WHERE $maxlifetime < unix_timestamp() - $last_time ";
return $DB->exec($sql);
}
开始操作:
1 . 可保证在第一个执行。将初始代码,在sessBegin完成,例如初始化数据库
结尾操作
1 . 进行扫尾工作
重写session存储机制2
- 要求:php>=5.4
bool session_set_save_handler ( SessionHandlerInterface $sessionhandler [, bool $register_shutdown = true ] );
- session存储接口
- 案例:
class MySessionHandler implements SessionHandlerInterface
{
private $savePath ;
public function open ( $savePath , $sessionName )
{
$this -> savePath = $savePath ;
if (! is_dir ( $this -> savePath )) {
mkdir ( $this -> savePath , 0777 );
}
return true ;
}
public function close ()
{
return true ;
}
public function read ( $id )
{
return (string)@ file_get_contents ( " $this -> savePath /sess_ $id " );
}
public function write ( $id , $data )
{
return file_put_contents ( " $this -> savePath /sess_ $id " , $data ) === false ? false : true ;
}
public function destroy ( $id )
{
$file = " $this -> savePath /sess_ $id " ;
if ( file_exists ( $file )) {
unlink ( $file );
}
return true ;
}
public function gc ( $maxlifetime )
{
foreach ( glob ( " $this -> savePath /sess_*" ) as $file ) {
if ( filemtime ( $file ) + $maxlifetime < time () && file_exists ( $file )) {
unlink ( $file );
}
}
return true ;
}
}
$handler = new MySessionHandler ();
session_set_save_handler ( $handler , true );
session_start ();
注意:
- 先设置在开启
session
机制 session_set_save_handler()
先于session_start()
被调用。- 不要自动开启
session
!(session.auto_start = 1
),否则会导致不能直接在程序里执行session
设置操作 - 建议将配置
session.save_handler=file
改为user
: 表示用户自定义
相关配置
1.session.save_handler
: 存储处理器(files|user 文件|用户自定义)
2. session.save_path
: 存储地址
3. session.cookie_XXX
: (lifetime,path,domain,secure,httponly)存储session_id
这个COOKIE变量的属性
4. session.gc_maxlifetime:session变量的有效期
5. session.gc_probability:session垃圾回收概率的被除数
6. session.gc_divisor:session垃圾回收概率的除数(基数)
session立即回收概率 =
session.gc_probability
/session.gc_divisor
session和cookie联系
- 都是会话技术
session
基于cookie
,session_id
存储于cookie
中
session和cookie区别
类型 | Cookie | session |
---|---|---|
存储位置 | 浏览器端 | 服务器端 |
安全性 | 低 | 高 |
大小限制 | 有 | 没有 |
数据类型 | 字符串 | 全部 |
有效期使用 | 长时间存储 | 几乎不做持久化 |
session持久化
- 浏览器存储session_id的cookie :
session_set_cookie_params(PHP_INT_MAX)
; - 服务器
session
数据区有效期修改:ini_set(‘session.gc_maxlifetime’, PHP_INT_MAX)
;
浏览器禁用cookie、session
- 设置session配置变量
//不仅用cookie传输session_id
ini_set('session.use_only_cookie','0');
//允许用url或表单等方式自动传输session_id
ini_set('session.use_trans_id','1');
- 通过 url 向服务器端传输
session_id
- 通过表单服务器端传输
session_id
<input type="hidden" name="PHPSESSID" value="o0sdfdsfdsfdfd..." />