session_start();
echo $sid = session_id();
$_SESSION['name']='zhezhao';
$_SESSION['age']=23;
我们可以看到,首次访问该页面,请求的http协议头并没有包含cookie信息;返回的http协议头包含了设置cookie信息的内容。设置cookie:PHPSESSID的值为session_id()的内容,有效期为当前会话,关闭浏览器则该cookie:PHPSESSID失效。
此时,浏览器的http请求头中包含了cookie:PHPSESSID的信息。
session_start();
函数会检查请求头中是否包含PHPSESSID的cookie信息,如果有则将其作为session的唯一标识,即session_id()的值。如果没有PHPSESSID的cookie信息,则重新生成一个session_id()并将该值设置为cookie:PHPSESSID的值。
首次访问该页面时,并没有任何cookie信息,所以此时php生成了session_id并在返回的http头文件中设置了PHPSESSID这个cookie的值。
再次访问页面的时候,http请求头文件中会包含该域名下的cookie,所以php就获取到了PHPSESSID的值,将其作为session_id()的值。
下面我们来解释一下,为什么session默认的有效期是浏览器的当前会话,关闭浏览器即失效;以及如何设置session的有效期?
在浏览器首次访问页面的时候,session_start()判断没有PHPSESSID这个cookie,所以自己生成了一个session_id()并将其设置为PHPSESSID的值。
我们注意到并没有设置cookie的有效期,所以使用的是cookie的默认有效期,即浏览器的当前会话,关掉浏览器,则PHPSESSID这个cookie就会失效,重新打开该页面的时候,http请求头就没有PHPSESSID这个cookie了,相当于一个新用户来访问。
所以session的默认过期时间和cookie的默认过期时间是一致的。
通过上面的分析,我们发现php在自动设置PHPSESSID这个cookie的值的时候,没有设置过期时间,所以cookie过期,session就过期了。
我们可以手动设置PHPSESSID这个cookie的过期时间,也就相当于设置了session的过期时间。
session_start();
echo $sid = session_id();
setcookie('PHPSESSID', session_id(), time() + 60*60); //设置过期时间为1小时
$_SESSION['name']='zhezhao';
$_SESSION['age']=23;
session在php中是通过文件存储的,存储路径可以在php的配置文件中找到
session.save_path ="c:/wamp64/tmp"
通过上面的分析,我们知道默认情况下,关闭浏览器。PHPSESSID这个cookie的值就会失效,再次访问该站点的时候,会重新生成一个PHPSESSID的值。然而,此时原来的PHPSESSID这个cookie的值虽然已经失效,但是session_id对应的存储session的文件可能还没有被删除,我们如果知道原来session_id的值的话,可以通过session_id("原来的session_id的值")
这个函数来实现恢复session的操作的。
那么存储session的文件在什么时候会被删除呢?
它和下面几个php的配置参数有关
session.gc_maxlifetime = 1440
session.gc_probability = 1
session.gc_divisor = 1000
gc_maxlifetime表示session的过期时间,从最后一次访问session开始算起,超过这个时间就会被当做系统垃圾,启动gc(垃圾清理)机制。
然而处于性能考虑,session过期之后,并不是会被立刻删除。而是有一定的概率(gc_probability/gc_divisor)被删除,默认情况下是0.1% ,也就是说有0.1%的概率,启动gc流程,清理cookie。每一次php请求,就会有1/1000的概率发生回收;1000次php请求,就会进行一次垃圾回收。
如果将gc_divisor的值也设置为1的话,启动gc的概率为1。也就是说,只要到达了gc_maxlifetime所设定的时间,就会立刻被清理。
重要补更
很多网站都有7天免登录功能,这种情况下cookie和session的生存时间都应该为7天。
设置cookie的有效期为7天
setcookie('PHPSESSID', session_id(), time() + 60*60*24*7); //过期时间为7天
上面讲过,session是以文件的形式存储在服务器上的,php通过session.gc_maxlifetime参数来决定session文件的过期时间,过期之后就可能会被清理。所以,我们需要将session的过期时间设置为7天。
session.gc_maxlifetime = 604800;
设置方法
修改php.ini的如下配置,并重启web服务器
session.use_trans_sid = 1;
session.use_only_cookies = 0;
通过上文,我们知道SESSION默认依赖cookie所传递的session_id的唯一标识SESSION。如果客户端禁用cookie时,我们还可以通过get的方式传递session_id,使SESSION正常工作。
修改php.ini生效之后,PHP编译器在将php文件进行解析时会做如下操作:
http://192.168.20.131/one.php?PHPSESSID=eckva0me0t1d4t4i3m8f496rb3
如何判断浏览器是否禁用了cookie呢?
echo defined('SID')?'true':'false';
可以通过SID是否被定义来判断,让cookie被禁用时,SID常量才会被定义。
通过输出我们可以发现SID的值就是通过URL进行传递的PHPSESSID=eckva0me0t1d4t4i3m8f496rb3
字符串。
事实上,cookie被禁用之后,SID常量就会被定义。但是要按照上面修改完php.ini的参数之后,才能SID才能作为session_id被SESSION使用。
在《HTTP权威指南》的第11章,有讲到在cookie之前的一些用户识别机制。
上面所讲到的通过URL传递seesion_id实际上就是书中所讲的“胖URL”技术,该技术存在以下缺点。
以上是个人的一些见解,如有不当,还请指出,谢谢。