[PHP]session的一些要点

一、session_start([array $options=array()])

1.只能在输出http头前启动此函数,因为如果需要改写sessid的键和值,需要在http报文头发出前就开始定义了;

2.$options有很多选项,包括设在sessid的键名(但是好像不包括设置值),sess CG启动频率,sess handler等等;

3.启动会话的session_id选取逻辑是,如果请求带有session_id的cookie,那么session_start()就用这个session_id,如果没有,则自己生成一个session_id,并且在响应报文的cookie中带回给客户端

二、session_name([string $name])

1.读取或设置sess的键名;

2.如果是设置,需要在调用session_start()之前;

3.设置sess的键名后,即使不调用session_id()函数,一个由系统生成的新的session_id也会被设置;

4.旧的sess cookie的键值对被废弃(此时浏览器还会保存旧的sess cookie的键值对,会带来一些风险,参考session_destroy());

三、session_id([string $id])

1.读取或设置sess的值;

2.如果是设置,需要在调用session_start()之前,否则会出现一种情况,调用session_start()后,包含旧的sess cookie的键值对的报文头已经生成,但是PHP进程中session_id()返回的值又被session_id()设置改变了,最终导致浏览器中的SESSID和PHP进程的SESSID不一致;

3.通过此函数可以为两个客户端设置同一个sessID,从而共用一个会话;

四、session_destroy()

1.销毁服务器中当前SESSID保存的值;

2.被销毁后的SESSID可以重用,例如销毁后浏览器依然保存着这个sess cookie的键值对,当浏览器重新请求带有session_start()的服务器脚本,服务器则重用这个SESSID,但是这相当于是一个新的SESSID,因为值在上一次访问时销毁了;

3.运用这一特性,可以实现用户多地点登录把上一个登录踢下线的操作:找个持久性保存数据处保存用户每一次登录的SESSID,登录前先查看用户是否有上一次登录的SESSID,如果有先把这个SESSID销毁,然后再进行新的登录,新的登录产生的SESSID重写到保存用户每一次登录的SESSID处;

4.需保持警惕的是,被销毁的ID有可能被其他用户会话重用,而此前被销毁的ID的用户浏览器cookie还保存着这个session_id,倘若如此,则会有读取到其他用户session的风险,所以应当在每次调用session_destroy()之前,调用setcookie()删除此session_id在客户端的cookie值

五、session_write_close()

当调用这个函数,线程将会把对会话变量的更改保存到session,并且释放该session(释放原因参见第六点);

 六、基于事务的session

同一时间只允许一个线程占用session,一旦有线程成功调用session_start(),其余线程调用session_start()会一直阻塞,直到占用线程退出,或调用session_destroy()、session_write_close();

七、在php手册中的sessions简介中(具体在,函数参考》session扩展》sessions简介),有一句这样的描述:

如果你打开了 session.auto_start 那么 将对象放入会话的唯一方法是使用 auto_prepend_file 来加载定义这个对象的类,其中,在加载的定义的类时,你不得不使用 serialize() 你得对象,并且事后 unserialize() 它

 

这句话的大致意思是,如果你想把一个对象,保存到session里面去,例如:

$_SESSION[‘OBJ’] = new SomeObject();

那么你必须在启动session会话前提前声明SomeObject,也就是说要在会话启动前把声明SomeObject的php文件加载进去,这需要使用到auto_prepend_file来实现;

原因是因为php会话内部机制是保存到会话这部分内存的内容,在保存的时候内部会调用serialize()把内容先序列化再保存,同样地在读出的时候会进行unserialize()反序列化再读出(即PHP内部初始化全局变量$_SESSION数组时会调用unserialize()),而又由于调用序列化系列函数序列化一个对象的前提是php必须知道这个对象是如何声明的,也就是说要在序列化之前包含对象的类声明文件,这就间接导致了启动session会话前必须包含相应的类文件了;

 

八、CLI和CGI环境的session是各自独立的,也就是说就是即使是相同的session id,在两种环境之间指向的也是不同的session,打个比方说,CLI环境下读取不到nginx+php-fpm环境下的http请求建立的session;

posted @ 2018-09-27 11:42  yiyide266  阅读(168)  评论(0编辑  收藏  举报