前面所提到的cookie技术,由于其存储于浏览器并且为明文存储,因此其在安全性不好,同时浏览器携带cookie数据请求时,会降低网络速度。
在此基础上使用会话技术---session。
浏览器发出请求后,在服务器响应时,可以设置session会话数据区(用来存储当前会话的全部数据),该数据区时独立的以文本的形式存储于当前服务器的temp文件夹(windows系统的临时文件夹)中。每个会话数据区在存储时会生成一个代表数据区的唯一标识符,并且该标识符在服务器将处理完数据后返回浏览器时,会将该唯一的标识符以cookie数据的形式存储于浏览器端。后面再浏览器再次请求时,会将该cookie的标识符携带到服务器端,通过该标识符与服务器端存储的session数据区相配对,通过这种方式完成会话。
实现语法:
1.开启session机制:session_start():函数开启;
2.利用$_SESSION操作session数据:操作$_SESSION与操作普通数组一样。
session_start();
$_SESSION['is_login']='yes';
通过上面程序设置session数据。我们可以在下面的结果中看到浏览器中的cookie数据区存在一个PHPSESSID名的数据。该数据的值即session数据区的唯一标识符。
session中的属性:和cookie的属性类似,
1.有效期:和cookie一样,默认为会话周期结束。
2.有效路径:默认为整站有效。
3.有效域:当前域有效(未设置时,子域也无法访问)。
4.是否仅安全连接:默认与cookie一样,false。
5.是否仅为HTTP使用:由于session存储于服务器中,因此浏览器的脚本无法获取。
注意:session数据的属性都是由浏览器端cookie中所存储的PHPSESSID变量的特征所导致的。这里要说明的一点是:在session数据被创建后,它是以文件的形式存储于临时文件目录中的,即使是当前会话结束也不会被删除,这是会话结束后无法再找到该session数据是因为浏览的端的cookie数据失效了,导致找不到与session对应的id。
因此要修改session数据的属性,就需要修改cookie数据中的PHPSESSID的属性:
1.更改php.ini配置文件(不建议)。
2.在脚本中,使用ini_set()来进行配置的修改,仅在设置后的脚本周期类有效,并且需要在开启session前设置完毕。
3.使用特定功能的函数:session_set_cookie_params('有效期','有效路径','有效域','是否仅安全传输','是否HTTPONLY')完成设置。
session相关机制:session_start()开启session机制
第一步:确定session-id。
第二步:初始化$_SESSION
<?php
var_dump($_SESSION);
session_start();
var_dump($_SESSION);
第一个var_dump($_SESSION)提示未定义变量,表名该变量初始时不存在的,只有当session_start()后开启session,$_SESSION才会存在,如第二个var_dump($_SESSION)就会显示出空数组。
第三步:session数据的持久化(脚本周期结束后完成,没结束前不会有相应的文本数据)
session销毁
session_destory();作用:1.删除当前session对应的数据区数据。
2.关闭session机制
注意:这里只是删除了数据区数据,但是$_SESSION已存在的数组数据并不会消失,并且关闭session机制保障了,脚本周期结束后,系统不会将$_SESSON中的数据持久化。(如果在销毁后再次使用session_start(),结束时会再次持久化$_SESSON数据)。
清空session数据可以使用:$_SESSION=array();利用空数组清空。
重写session存储机制:
通过定义相关的存储处理函数,将其设置为session机制需要的存储函数(与定义自动掉用函数相似);
使用PHP中的函数:session_set_save_handler(开始处理(函数名,可自定义),结束处理,读取处理,写入处理,删除处理,垃圾回收处理);它包含留个参数,按照顺序为存储机制对应各个功能,其函数名可以自定义。函数定义的时候可以不存在顺序,但是session_set_save_handler()声明各个函数功能是的参数顺序不能变。
<?php
public function sessionBegin(){
}
public function sessionEnd(){
}
public function sessionRead(){
}
public function sessionWrite(){
}
public function sessionDelete(){
}
public function sessionGC(){
}
session_set_save_handler(
'sessionBegin',
'sessionEnd',
'sessionRead',
'sessionWrite',
'sessionDelete',
'sessionGC'
);
正常情况下,session开启的操作顺序是:sessionbegin->sessionread->sessionwrite->sessionend.至于sessiondelete是在调用session_destory()是才调用的。而sessionGC这是在sessionRead之后按照一定概率执行。
各个函数的实现。:
开始和结束:
<?php
//在数据库中记录对应的session文件。
create table `session`(
session_id varchar(32) not null default '' primary key,
session_content text,
laster_time int not null default 0
)charset=utf8;
public function sessionBegin(){
//session开启时调用
}
public function sessionEnd(){
//session关闭时调用。
}
从数据库读取数据区:
/**
*session机制开启过程中执行,目的是从当前session数据区读取内容。
*@param $sess_id string 依靠id读取内容
*@return string 返回一个数据内容
**/
public function sessionRead($sess_id){
//初始化数据库服务器;
$link=mysql_connect('localhost','root','root')or die('连接失败!');
mysql_query('set names utf8');
mysql_query('use 数据库名');
//查询
$sql="select session_content from `session` where session_id=$sess_id";
$result=mysql_query($sql);
if($reocrd=mysql_fetch_assoc($result)){
return $record;
}else{
return '';//没有对应的id,返回空字符串。
}
}
将数据写入数据库(持久化数据)
/**
*当前脚本周期结束时,处理脚本的session数据,持久化存储到数据库中。
*@param $sess_id 需要操作的session数据的id
*@param $sess_content 序列化号的session内容(字符串)。
*return bool 判断是否写入成功。
**/
public function sessionWrite($sess_id,$sess_content){
//初始化数据库服务器;
$link=mysql_connect('localhost','root','root')or die('连接失败!');
mysql_query('set names utf8');
mysql_query('use 数据库名');
//写入(持久化存储)。
$sql="replace into 数据库名 values ('$sess_id','$sess_content')";//replace语法与insert一样,主键存在(冲突)则替换,不存在则插入
return mysql_query($sql);//
}
删除数据库中的session数据:在调用session_destory()时会自动调用。
/**
*删除操作:用户调用session_destroy($sess_id)时,销毁session数据。(删除数据区数据)
*@param $sess_id session的id
*@return bool 返回一个删除操作结果。
**/
public function sessionDelete($sess_id){
//初始化数据库服务器;
$link=mysql_connect('localhost','root','root')or die('连接失败!');
mysql_query('set names utf8');
mysql_query('use 数据库名');
//删除数据库中的session数据。
$sql="delete from 表名 where $sess_id=session_id";
if(mysql_query($sql)){
return true;
}else{
return false;
}
}
垃圾回收函数重写:
垃圾识别,可以给数据库添加一个时间类型数据,记录其最后一次处理后时间戳。如果登入后,间隔上次时间超过规定时间(多久未登入),则被视为垃圾数据,删除。
‘最后一次更新’可以在写操作将其更新。
$sql="replace into 数据库名 values ('$sess_id','$sess_content',unix_timestamp())";
GC执行:在开启session机制过程中,有一定概率在执行完读取操作后执行垃圾回收操作。
这里的一定概率是指在配置文件中设置的session.gc_probability(分子)和session.gc_divisor(分母)来进行概率设定。
/**
*开启session机制时,有一定概率删除那些过期的session数据区。
*@param $life_time 数据存在的生命周期。
*return bool 返回数据库操作结果。
**/
public function sessionGC($life_time){
//初始化数据库服务器;
$link=mysql_connect('localhost','root','root')or die('连接失败!');
mysql_query('set names utf8');
mysql_query('use 数据库名');
//删除数据库中过期的session数据。
$sql="delete from 表名 where last_time<unix_timestamp()-$life_time";
return mysql_query($sql);
}
注意:对于上面的函数使用session_set_save_handler()声明时,参数为函数名即可
session_set_save_handler(
'sessionBegin',
'sessionEnd',
'sessionRead',
'sessionWrite',
'sessionDelete',
'sessionGC'
);
但是当把上面的重写操作作为类使用时,里面的名字为方法名。这是如果用session_set_save_handler()进行声明时,是对类中的方法进行声明。这是需要其对应方法的对象。
session_set_save_handler(
array($this'sessionBegin'),
array($this'sessionEnd'),
array($this,'sessionRead'),
array($this,'sessionWrite'),
array($this,'sessionDelete'),
array($this,'sessionGC')
);
设置session处理器
设置配置文件中的session.save_handler来对其存储方式进行设定。
原文件中的session.save_handler=files表示将session数据存储在临时文件夹的文本文件中。
当我们重写session存储机制后,最后通过ini_set('session.save_handler','user');来表示用户自定义session机制。