阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

关于PHP sessions的超时设置

215次阅读
没有评论

共计 3068 个字符,预计需要花费 8 分钟才能阅读完成。

介绍

这篇文章致力于解释为什么要设置非活动时间后使 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 超时时间。

<?php
/***
 * 开启 session, 并指定超时时间及指定 php 的 session 垃圾回收机率
 * @param int $timeout 多少秒后设置为超时
 * @param int $probability 设置垃圾回收机率
 * @param strint $cookie_domain cookie 的域名路径
 */
function session_start_timeout($timeout=5, $probability=100, $cookie_domain=’/’) {
    // 设置 session 的最大生命周期
    ini_set(“session.gc_maxlifetime”, $timeout);
 
    // 设置 session cookie 的超时时间
    ini_set(“session.cookie_lifetime”, $timeout);
 
    // 改变保存路径。相同生命周期的 sesion 保存于相同目录中。
    // 于是保存于同一目录中的 session 的生命周期由最低的生命周期 session 来决定。
    // 因此,为了让它工作起来,相同目录下的 session 必需要相同的生命周期。最好的就是动态创建。
    $seperator = strstr(strtoupper(substr(PHP_OS, 0, 3)), “WIN”) ? “\\” : “/”;
    $path = ini_get(“session.save_path”) . $seperator . “session_” . $timeout . “sec”;
    if(!file_exists($path)) {
        if(!mkdir($path, 600)) {
            trigger_error(“Failed to create session save path directory ‘$path’. Check permissions.”, E_USER_ERROR);
        }
    }
    ini_set(“session.save_path”, $path);
 
    // 设置 session 垃圾回收机率
    ini_set(“session.gc_probability”, $probability);
    ini_set(“session.gc_divisor”, 100); // 应该要设置为 100
 
    // 启动 session
    session_start();
 
    // 重置保存时间,直到 session 超时.
    // 如果你跳过这一步,session 的超时时间是基于创建 session 的时间,而不是基于上次使用的时间。
    if(isset($_COOKIE[session_name()])) {
        setcookie(session_name(), $_COOKIE[session_name()], time() + $timeout, $cookie_domain);
    }
}

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

session_start_timeout(60);

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

session_start_timeout(60, 10);

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

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-02/140488.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计3068字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中