如何在PHP中更改会话超时时间?

13 浏览
0 Comments

如何在PHP中更改会话超时时间?

我想延长php中的会话超时时间。

我知道可以通过修改php.ini文件来实现。

但是我无法访问该文件。

所以是否可能只使用php代码来实现?

0
0 Comments

在PHP中更改会话超时的方法及原因:

会话超时是一个需要在代码中实现的概念,如果您希望严格保证,这是唯一的方法,您可以绝对确定,在X分钟的不活动后,没有会话会继续存在。

如果在宽松的环境中放宽这个要求,并且您对持续时间的严格限制进行一些限制,您可以轻松地进行调整,而无需编写自定义逻辑。

在宽松的环境中的便利性:如何以及为什么

如果您的会话是通过cookie实现的(这可能是您的情况),而且客户端不是恶意的,您可以通过调整某些参数来设置会话持续时间的上限。如果您正在使用PHP的默认会话处理与cookie一起使用,那么设置session.gc_maxlifetime以及session_set_cookie_params应该可以满足您的要求,如下所示:

// 服务器至少应保留会话数据1小时

ini_set('session.gc_maxlifetime', 3600);

// 每个客户端应该记住他们的会话ID正好1小时

session_set_cookie_params(3600);

session_start(); // 准备就绪!

这是通过配置服务器在一小时的不活动时间内保留会话数据,并指示客户端在相同的时间段后“忘记”他们的会话ID来工作的。要实现预期的结果,这两个步骤都是必需的。

如果您不告诉客户端在一小时后忘记他们的会话ID(或者如果客户端是恶意的并选择忽略您的指示),他们将继续使用相同的会话ID,其有效持续时间将是不确定的。这是因为在服务器端已过期的会话只有在会话垃圾回收(session GC)启动时才会被立即清除。

GC是一个可能很昂贵的过程,所以通常概率相当小,甚至为零(一个网站获得大量点击的情况下,可能会完全放弃概率GC,并安排在后台每隔X分钟发生一次)。在这两种情况下(假设客户端不合作),会话生存时间的最小值将是session.gc_maxlifetime,但上限将是不可预测的。

如果您不将session.gc_maxlifetime设置为相同的时间段,那么服务器可能会在此之前丢弃闲置会话数据;在这种情况下,仍记得他们的会话ID的客户端将呈现它,但服务器将找不到与该会话相关联的数据,实际上会表现得像会话刚开始一样。

关键环境中的确定性

通过使用自定义逻辑还可以完全控制事物,以在会话不活动时也放置上限;与上述的下限相结合,这将得到一个严格的设置。

通过将上限与其余会话数据一起保存来实现这一点:

session_start(); // 准备就绪!

$now = time();

if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {

// 这个会话已经过期,杀死它并开始一个全新的

session_unset();

session_destroy();

session_start();

}

// 无论是新的还是旧的,它应该再活1小时

$_SESSION['discard_after'] = $now + 3600;

会话ID的持久性

到目前为止,我们对每个会话ID的具体值一直不关心,只关心数据在我们需要的时间内存在。请注意,在(不太可能的)情况下,会话ID对您很重要,必须小心在需要时使用session_regenerate_id重新生成它们。

问题:如果每分钟调用一次,会增加它的限制吗?例如,10:00我调用它,所以它的限制将是11:00,在1分钟后,10:01,限制将是11:01吗?

如果你调用什么?

这些:ini_set('session.gc_maxlifetime', 3600); session_set_cookie_params(3600);

是的,但只有在你也调用session_start()(否则根本没有效果),并且只有在你总是在session_start()之前调用这两个函数(否则gc_maxlifetime有可能影响当前打开的所有会话,而session_set_cookie_params只能影响使用当前请求开始的新会话)。

如果我再次调用session_start(),它会重置我的$_SESSION中的所有内容吗?

如果你的意思是“有潜力影响所有会话”,那么是的,如果你在调用session_start()之前总是调用那两个函数的话(否则gc_maxlifetime有影响当前打开的所有会话的潜力,而session_set_cookie_params只能影响使用当前请求开始的新会话)。

如果我不使用cookie,我不需要写这个对吗?

如果您使用会话ID作为GET参数,那么您可能不需要设置cookie计时器,但是您需要运行GC或自定义逻辑(取决于其重要性),以便用户无法重复使用会话ID(甚至可能是意外的,因为它将在URL栏和历史记录中显示给用户)。

我认为这个答案特别好,因为它展示了关键和非关键的部分。我个人使用PHP会话主要用于非关键的东西,比如错误消息等,而使用基于数据库的会话和自己的cookie来进行真正关键的操作,这样,带有适当过滤器的删除命令就可以将所有旧会话清除。

stackoverflow上最好的答案之一!谢谢!很多人忽略了为什么,只是跳到了如何。这让我成为了一个更好的程序员,而不仅仅是一个更好的复制者。希望有更多像这样的答案。

如果您在共享服务器上,您可能还需要设置“session.save_path”才能使其正常工作。除了忽略该点之外,这是一个很好的答案。

0
0 Comments

如何在PHP中更改会话超时时间?

如果您使用PHP的默认会话处理方式,可靠地在所有平台上更改会话持续时间的唯一方法是更改php.ini。这是因为在某些平台上,垃圾回收是通过每隔一段时间运行的脚本(cron脚本)来实现的,该脚本直接从php.ini中读取,并且因此在运行时通过ini_set()等方式尝试更改它是不可靠的,很可能不起作用。

例如,在Debian Linux系统中,默认情况下通过将session.gc_probability=0设置在配置中来禁用PHP的内部垃圾回收,并且是通过/etc/cron.d/php执行的,它在XX:09和XX:39(即每半小时)运行。此cron作业查找超过配置中指定的session.gc_maxlifetime的会话,如果找到任何会话,则将其删除。因此,在这些系统中,ini_set('session.gc_maxlifetime', ...)将被忽略。这也解释了为什么在这个问题中:PHP会话超时太快,OP在一个主机上遇到了问题,但在切换到另一个主机后问题消失了。

因此,鉴于您无法访问php.ini,如果要以可移植的方式进行更改,使用默认的会话处理方式是不可行的。显然,延长cookie的生存时间对您的主机来说已经足够了,但如果您想要一个可靠地适用于切换主机的解决方案,您必须使用不同的替代方法。

可用的替代方法包括:

1. 在PHP中设置不同的会话(保存)处理程序,将会话保存在不同的目录或数据库中,如PHP手册中所述,以使cron作业无法访问,只进行PHP的内部垃圾回收。该选项可能可以使用ini_set()来设置session.gc_maxlifetime,但我更喜欢在我的gc()回调中忽略maxlifetime参数,并自行确定最大生存时间。

2. 完全忽略PHP内部会话处理,实现自己的会话管理。这种方法有两个主要缺点:您将需要自己的全局会话变量,因此失去了$_SESSION超全局变量的优势,并且需要更多的代码,因此存在更多的错误和安全漏洞的机会。最重要的是,会话标识符应由加密安全的随机或伪随机数生成,以避免会话ID可预测性(可能导致会话劫持),而这在PHP中并不容易实现。主要的优点是它将在所有平台上一致工作,并且您对代码拥有完全的控制。这是例如由phpBB论坛软件采用的方法(至少在1版本中,我不确定更近期的版本)。

session_set_save_handler()的文档中有一个(1)的示例。该示例很长,但我将在此处复制它,并进行必要的修改以扩展会话持续时间。请注意,还包括使用session_set_cookie_params()来增加cookie的生存时间。

以下是示例代码:

savePath = 'my_savepath'; // 忽略savepath并使用我们自己的路径以使其安全免受自动GC影响
        $this->lifetime = 3600; // 最小会话持续时间为1小时
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }
        return true;
    }
    function close()
    {
        return true;
    }
    function read($id)
    {
        return (string)_get_contents("$this->savePath/sess_$id");
    }
    function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }
    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }
        return true;
    }
    function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // 使用我们自己的生存时间
                unlink($file);
            }
        }
        return true;
    }
}
$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
);
// 以下防止使用对象作为保存处理程序时出现意外效果
register_shutdown_function('session_write_close');
session_set_cookie_params(3600); // 将会话cookie持续时间设置为1小时
session_start();
// 继续按键从$_SESSION设置和检索值

方法(2)更加复杂;基本上,您必须自己重新实现所有会话函数。我不会在这里详细介绍。

有人可以确认一下吗?

:在粗略阅读后,看起来是正确的。您还可以参考stackoverflow.com/questions/520237/...,但如果您无法访问php.ini,则您的实际选项受到严格限制。

此外,在Ubuntu 14上,看起来/usr/lib/php5/maxlifetime将不会计算低于24分钟的值。因此,您无法将会话超时时间设置得低于该值。

“完全忽略PHP内部会话处理并实现自己的会话管理。”天哪,这是危险的建议。这将不可避免地导致安全噩梦。

我还注意到“它需要更多的代码,因此有更多的错误和安全漏洞的机会”。这不是建议,我正在列举替代方案,但如果您有改进的建议,请告诉我。

session.gc_probability根据文档的说法默认为1 - php.net/manual/en/...

0