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

我想在 php 中延长会话超时

我知道通过修改 php.ini 文件可以做到这一点。 但我没有权限。

那么是否有可能只使用 php 代码来完成呢?

395404 次浏览

如果不能访问 php.ini,就不能保证更改会产生任何效果。

不过我觉得你不需要延长治疗时间。
目前它有相当合理的超时,没有理由扩展它。

可以使用 ini_set()从 PHP 代码覆盖 PHP.ini 中的值。

会话超时是一个必须在代码中实现的概念,如果您想要得到严格的保证; 这就是 唯一的办法,您可以完全确定,在 X 分钟的不活动之后,任何会话都不会存活。

如果稍微放松这个要求是可以接受的,并且您可以放置 下界而不是对持续时间的严格限制,那么您可以很容易地做到这一点,而且不需要编写自定义逻辑。

轻松环境中的方便: 如何和为什么

如果 您的会话是使用 cookie 实现的(它们可能是) ,并且 如果客户端没有恶意,您可以通过调整某些参数来设置会话持续时间的上限。如果您使用 PHP 的默认会话处理 cookie,设置 session.gc_maxlifetimesession_set_cookie_params应该这样工作:

// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);


// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);


session_start(); // ready to go!

这是通过配置服务器使会话数据保持至少一个小时的不活动状态,并指示您的客户端在相同的时间跨度之后应该“忘记”会话 ID 来实现的。要达到预期的结果,这两个步骤都是必需的。

  • 如果你不告诉客户在一个小时后忘记他们的会话 ID (或者如果客户是恶意的,选择忽略你的指令) ,他们将继续使用相同的会话 ID,其有效持续时间将是不确定的。这是因为服务器端生存期已过的会话不会立即进行垃圾回收,而只会进行 每当会话 GC 启动时回收。

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

  • 如果你没有将 session.gc_maxlifetime设置为相同的时间跨度,那么服务器可能会在此之前丢弃空闲的会话数据; 在这种情况下,仍然记得会话 ID 的客户端将显示它,但是服务器将找不到与该会话相关的数据,有效地表现为会话刚刚开始。

关键环境下的确定性

通过使用自定义逻辑将 上界放在会话不活动上,可以使事情完全可控; 再加上上面的下限,这将导致严格的设置。

为此,请将上限与会话数据的其余部分一起保存:

session_start(); // ready to go!


$now = time();
if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {
// this session has worn out its welcome; kill it and start a brand new one
session_unset();
session_destroy();
session_start();
}


// either new or old, it should live at most for another hour
$_SESSION['discard_after'] = $now + 3600;

会话 ID 持久性

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

如果使用 PHP 的默认会话处理,在所有平台上可靠地更改会话持续时间的唯一方法是更改 Php.ini。这是因为在一些平台中,垃圾收集是通过一个每次都运行的脚本(一个 Cron脚本)来实现的,这个脚本直接从 Php.ini读取,因此任何在运行时更改它的尝试,例如通过 ini_set(),都是不可靠的,而且很可能不会起作用。

例如,在 Debian Linux 系统中,PHP 的内部垃圾收集是通过在配置中默认设置 session.gc_probability=0来禁用的,而是通过/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: 自定义会话处理程序(PHP 手册)中指定的那样,这样 Cron作业就不会到达它,只有 PHP 的内部垃圾收集会发生。这个选项可能可以利用 ini_set()来设置 Session.gc _ maxlifetime,但是我更喜欢忽略 gc()回调中的 最大寿命参数,自己确定最大生存期。

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

session_set_save_handler()的文件中有一个(1)的例子。这个示例很长,但是我将在这里重新创建它,以及扩展会话持续时间所需的相关修改。注意,包含 session_set_cookie_params()也增加了 Cookie 的生存期。

<?php
class FileSessionHandler
{


private $savePath;
private $lifetime;


function open($savePath, $sessionName)
{
$this->savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC
$this->lifetime = 3600; // 1 hour minimum session duration
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}


return true;
}


function close()
{
return true;
}


function read($id)
{
return (string)@file_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)) { // Use our own lifetime
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')
);


// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');


session_set_cookie_params(3600); // Set session cookie duration to 1 hour
session_start();
// proceed to set and retrieve values by key from $_SESSION

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

$_SESSION['login_time'] = time();放入上一个身份验证页。 以及下面要检查会话超时的每个其他页面中的剪辑。

if(time() - $_SESSION['login_time'] >= 1800){
session_destroy(); // destroy session.
header("Location: logout.php");
die(); // See https://thedailywtf.com/articles/WellIntentioned-Destruction
//redirect if the page is inactive for 30 minutes
}
else {
$_SESSION['login_time'] = time();
// update 'login_time' to the last time a page containing this code was accessed.
}

编辑: 只有当您已经在其他文章中使用了调整,或者禁用了垃圾收集,并且希望手动检查会话持续时间时,此功能才能工作。 不要忘记在重定向之后添加 die(),因为有些脚本/机器人可能会忽略它。此外,直接销毁与 session_destroy()会话,而不是依赖于一个重定向,这可能是一个更好的选择,再次,如果是一个恶意的客户端或机器人。

为任何使用 Plesk 的用户添加注释,因为它让我抓狂,从 PHP 脚本中设置 session.gc _ maxlife 不会起作用,因为 Plesk 有自己的从 cron 运行的垃圾收集脚本。

为了避免这个问题,我使用了下面链接中的解决方案,将 cron 作业从每小时转移到每天,然后上面的顶部答案应该可以起作用:

mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/

Https://websavers.ca/plesk-php-sessions-timing-earlier-expected

只是一个 共享主机服务器的通知,或者添加到域中 =

为了使设置正常工作,您必须使用 php_value session.save_path folderA/sessionsA为添加的域设置一个不同的保存会话目录。

因此,创建一个文件夹到您的根服务器,而不是到 public_html和不公开从外部访问。对于我的 cpanel/server 工作良好的文件夹权限 0700。试试看..。

# Session timeout, 2628000 sec = 1 month, 604800 = 1 week, 57600 = 16 hours, 86400 = 1 day
ini_set('session.save_path', '/home/server/.folderA_sessionsA');
ini_set('session.gc_maxlifetime', 57600);
ini_set('session.cookie_lifetime', 57600);
# session.cache_expire is in minutes unlike the other settings above
ini_set('session.cache_expire', 960);
ini_set('session.name', 'MyDomainA');

session_start();之前

或者把这个放到你的 .htaccess文件里。

php_value session.save_path /home/server/.folderA_sessionsA
php_value session.gc_maxlifetime 57600
php_value session.cookie_lifetime 57600
php_value session.cache_expire 57600
php_value session.name MyDomainA

经过多次研究和测试,这种方法在共享 cpanel/php7服务器上运行良好