英文出自: 

介绍

这篇文章致力于解释为什么要设置非活动时间后使PHP session失效的原因。以及这个机制是怎样运行的。我会描述两种通用的方法去控制php Session的生命周期,及怎样在你的代码中实现。

问题

PHP的session机制允许我们为客户端在服务器端保存数据,并使数据存留于多个请求中。然而因为数据它本身是保存在服务器端的,并且客户端与服务器端他们各自的session的连接是通过一个简单的cookie进行的,这个产生了一个很大的安全问题。

一个称为session劫持就是利用从客户端恶意第三方拦截或劫取session cookie,然后使用它去访问一个活跃session的数据。对于这个服务器几乎是不能防御,因为它没办法去告诉有劫持的原始客户端。

解决

对于session劫持的一个重要的防御就是忽略过期session。这个能阻止劫持者使用session,除非他们能在sesion指定的时间里实时使用。

在php中实现了这种称为session垃圾回收的机制。数据文件被标上了最后修改的时间戳,用于php来确定用户最后一次会话的时间。如果会话比允许的会话周期时间要长,它就会被销毁。在php中的默认会话周期是1440秒,或是24分钟。

我们会碰到想手动配制会话生命周期的情况。这样能更好的控制会话超时时间。这里有两种方法我们能够做到这一点。

方法1:手动编码完成

你能简单的在网站的每一个页面中添加一个代码片段,这个代码片段中用当前时间去设置一个会话字段。然后使用这个字段去决定一个会话的非活跃时间和相应的动作。例如:

session_start();$timeout = 60; // 设置非活跃session失效时间 // 检查超时session是否存在if(isset($_SESSION['timeout'])) {    //查看这次与最近一次的访问时间间隔是不是大于超时时间    $duration = time()- (int)$_SESSION['timeout'];    if($duration > $timeout) {        //销毁session并重启session        session_destroy();        session_start();    }} // 用当前时间更新超时字段$_SESSION['timeout'] = time();

方法2:配置PHP的session垃圾回收

PHP.ini中的session.gc_maxlifetime指令控制着session被作为垃圾清除之前所存在的时间。第一个调用session_start()方法都有机会触发垃圾回收的运行。而解发的机会由两个指令决定,其为session.gc_probability及session.gc_divisor。触发的可能性计算公式为:session.gc_probability/session.gc_divisor。

这两个指令默认值分别为1和100,也就是说有1%的机会能触发垃圾回收。如果你网站不是特别的堵,你可以把指令session.gc_probability这个值设置大一点,这样触发的机会会更大。如果你想要保证它们是100%的运行,那么你就把这两个指令的值设置为一样即可。

另一个要考虑的就是php储存session数据的目录。php把相同生命周期的session数据文件保存于同一目录中;最小的生命周期也是一样的。这就意味着如果你想准确确定你的session是否过期,你就需要使用你自己的目录了。最好的方法就是在你的主目录或临时目录下创建一个目录。你可以使用php的mkdir方法在创建目录,并通过session.save_path这个指令来改变session数据保存路径。

这些指令的值可以通过ini_set方法来设置,所以你能在每一个请求的基础上设置session垃圾回收值。例如,下面这个方法就是开启session,并设置session超时时间。

设置一个session的超时时间为一分钟,我们可以像如下那样调用上面的方法:

session_start_timeout(60);

默认情况下,上面的方法是百分之百触发php sessin垃圾回收机制。在一个高通信量的网站上,它会使用服务器很吃紧的。解决的方式,就是通过方法的第二个参数把触发机率改小一点。如:

session_start_timeout(60, 10);

这样就只有百分之十的机率来解发php的session垃圾回收运行机制了。