浅谈cookie和session的关系


session_start();
echo $sid = session_id();
$_SESSION['name']='zhezhao';
$_SESSION['age']=23;

首次访问

首次访问该页面
浅谈cookie和session的关系_第1张图片

我们可以看到,首次访问该页面,请求的http协议头并没有包含cookie信息;返回的http协议头包含了设置cookie信息的内容。设置cookie:PHPSESSID的值为session_id()的内容,有效期为当前会话,关闭浏览器则该cookie:PHPSESSID失效。

再次访问

然后我们刷新一下,再访问该页面
浅谈cookie和session的关系_第2张图片

此时,浏览器的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的默认有效期

在浏览器首次访问页面的时候,session_start()判断没有PHPSESSID这个cookie,所以自己生成了一个session_id()并将其设置为PHPSESSID的值。

这里写图片描述
我们注意到并没有设置cookie的有效期,所以使用的是cookie的默认有效期,即浏览器的当前会话,关掉浏览器,则PHPSESSID这个cookie就会失效,重新打开该页面的时候,http请求头就没有PHPSESSID这个cookie了,相当于一个新用户来访问。

所以session的默认过期时间和cookie的默认过期时间是一致的。

修改session的失效时间

通过上面的分析,我们发现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;

这里写图片描述

php对session的处理机制

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;

通过get方式传递session_id

设置方法

修改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文件进行解析时会做如下操作:

  1. 在所有的站内url后面添加PHPSESSIOD参数,对于http://www.baidu.com这种站外url无效 。
  2. 在session_start();命令执行之前,会自动执行如下操作session_id($_GET[“PHPSESSID”]) 。
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之前的一些用户识别机制。
浅谈cookie和session的关系_第3张图片

上面所讲到的通过URL传递seesion_id实际上就是书中所讲的“胖URL”技术,该技术存在以下缺点。
这里写图片描述
浅谈cookie和session的关系_第4张图片

以上是个人的一些见解,如有不当,还请指出,谢谢。

你可能感兴趣的:(PHP)