深入理解 Session 的过期机制

96
斐波那契额
2018.03.08 14:58 字数 698

首先得明白:

session 的过期时间由两方面决定的;

  • 存储在客户端的 $_COOKIE[‘PHPSESSID’] 的过期时间(默认cookie名称为 PHPSESSID,可通过 php.ini 中的 session.name 修改。)

  • 存储在服务器端的相对应的 session 文件(session 文件名和上述 cookie的值一一对应),默认为 1440 秒,即 24 分钟

ok,现在详细阐述上述两者的关系: 当执行 session_start() 的时候,其实是做了两件事:

  • 检查客户端发送过来的的所有 cookie(当然也包括 $_COOKIE[‘PHPSESSID’], 如果有的话),根据 $_COOKIE[‘PHPSESSID’] 的值(这是由 apache 产生的随机字符串,如 0lkbd2se458r600m2m7o1r4ic5)来访问 相对应的 session文件(如:sess_0lkbd2se458r600m2m7o1r4ic5,我的默认存储在‘E:\wamp\tmp’下),这两者是一 一对应的关系。打个比喻:
$_COOKIE[‘PHPSESSID’] 就是一把开启宝盒的钥匙,而那个宝盒就是 session 文件,里面存储着用户的重要 信息,也就是 session 的值, 如:$_SESSION[‘uid’]=1, $_SESSION[‘username’]=’name’, $_SESSION[‘pwd’]=’pwd’, 当然文件里面的值是经过序列化的。
  • 如果客户端没有传来 $_COOKIE[‘PHPSESSID’],就会有服务端产生一个随机的 $_COOKIE[‘PHPSESSID’] 并存储在客户端。

明白上面这些,我们可以通过下面的方法修改 session 的过期时间:

// 修改 $_COOKIE[‘PHPSESSID’] 的生存时间为50秒
session_set_cookie_params(’50’);    

// 或者可以这样: 
setcookie(session_name(), session_id(), time()+50);
// 设置 session 文件的有效时间为 50 秒
ini_set(‘session.gc_maxlifetime’, ’50’);

但是,可能有些朋友会做这样一个试验, 在 50 秒内获取 $_COOKIE[‘PHPSESSID’] 的值并记录下来(如黑客截获这个 cookie),这样等 50 秒过后发现原先的 $_COOKIE[‘PHPSESSID’] 值确实不存在了,而出现了一个新的 $_COOKIE[‘PHPSESSID’],但是 ‘E:\wamp \tmp’ 下的旧 session 文件却没有消失(默认只有 1/1000 的概率会消失,应该不会碰到吧,呵呵),这是为什么呢?我不是已经设置了 .ini_set(‘session.gc_maxlifetime’,’50’); 了吗?再做一个实验:这时你伪造一个 $_COOKIE[‘PHPSESSID’], 值为刚才你记录下的,神奇的事发生了,你依然可以访问刚才旧的 session 文件!!!(虽然他已经过期),只要这个文件没被删除,用相对应得 $_COOKIE[‘PHPSESSID’] 依然可以进行访问!!!

那我们设置 ini_set(‘session.gc_maxlifetime’, ’50’); 还有什么意义呢?这就涉及的 GC(GarbageCollector) 的回收机制。

默认情况下,session.gc_probability = 1session.gc_divisor=1000,也就是说有 1/1000 的可能性会启动 GC。GC 的工作,就是扫描所有的 session 信息,用当前时间减去 session 的最后修改时间(modifieddate),同session.gc_maxlifetime 参数进行比较,如果生存时间已经超过gc_maxlifetime,就把该 session 删除。只要没有启动 GC,即使 session 过期,也仍旧可通过相对应得 $_COOKIE[‘PHPSESSID’] 进行访问!

技术
Web note ad 1