我希望延长php会话超时时间。
我知道可以通过修改php.ini文件来实现,但是我没有权限访问它。
那么只使用php代码是否可能实现?
我希望延长php会话超时时间。
我知道可以通过修改php.ini文件来实现,但是我没有权限访问它。
那么只使用php代码是否可能实现?
如果您想要严格保证,必须在代码中实现会话超时并设定一个时间限制;这是唯一的方法,您可以绝对确信,在X分钟的不活动后,没有任何会话会被保留。
如果放宽这个要求有一些可接受,并且您愿意将持续时间的限制改为下限,那么您可以轻松地进行设置,而无需编写自定义逻辑。
如果您的会话是使用cookie实现的(很可能是这样),并且如果客户端没有恶意,则可以通过调整某些参数来设置会话持续时间的上限。如果您正在使用PHP的默认会话处理方式来处理cookie,则可以通过设置session.gc_maxlifetime
以及session_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的客户端将呈现该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 时,必须谨慎处理并使用 session_regenerate_id
在需要重新生成会话 ID 时。
session_start()
(否则根本没有效果)并且只有在您在session_start
之前始终调用这两个函数时(否则gc_maxlifetime
可能会影响当前打开的所有会话,而session_set_cookie_params
只能影响使用当前请求开始的新会话)。 - Jonini_set()
)是不可靠的,并且很可能无法正常工作。session.gc_probability=0
设置为禁用PHP内部垃圾回收,并且是通过/etc/cron.d/php来完成的,该文件在XX:09和XX:39(即每半个小时)运行。此cron作业查找比配置中指定的session.gc_maxlifetime旧的会话,如果找到任何会话,则将其删除。因此,在这些系统中ini_set('session.gc_maxlifetime', ...)
被忽略。这也解释了为什么在这个问题中:PHP sessions timing out too quickly,OP在一个主机上遇到问题,但切换到另一个主机后问题消失了。在 PHP 中设置一个不同的会话(保存)处理程序,将您的会话保存到不同的目录或数据库中,如 PHP:自定义会话处理程序(PHP手册) 中所指定,以便 cron 作业无法访问它,只有 PHP 的内部垃圾回收才会发生。这个选项可能可以使用 ini_set()
来设置 session.gc_maxlifetime,但我更喜欢在我的 gc()
回调中忽略 maxlifetime 参数并自行确定最大生存期。
完全忘记 PHP 内部会话处理,并实现自己的会话管理。此方法有两个主要缺点:您将需要自己的全局会话变量,因此失去了 $_SESSION
超全局变量的优势,而且需要更多的代码,因此存在更多的漏洞和安全隐患。最重要的是,会话标识符应该由加密安全的随机或伪随机数生成,以避免会话 ID 可预测性(导致可能的会话劫持),而这在 PHP 中不太容易实现。主要优点是它将在所有平台上一致工作,并且您对代码拥有完全控制权。这是例如 phpBB 论坛软件采取的方法(至少是版本 1;我不确定更近期的版本)。
在session_set_save_handler()
的文档中有一个示例。虽然示例很长,但我将在此处重现它,并进行相关修改以延长会话持续时间。请注意,还包括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
第二种方法比较复杂,基本上你需要自己重新实现所有的会话函数。我这里不会详细介绍。
/usr/lib/php5/maxlifetime
不会计算低于24分钟的值。因此,您无法将会话超时设置为低于该值。 - Henrysession.gc_probability
根据文档默认为 1 - https://www.php.net/manual/zh/session.configuration.php#ini.session.gc-probability - Jacob Thomason针对使用共享主机或添加域名的注意事项 =
要使您的设置生效,必须为添加的域名使用不同的保存会话目录,方法是使用 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服务器运行良好。非常感谢:NoiS
针对使用 Plesk 遇到以上任何问题的用户,我想提供一些帮助。这个问题曾经让我很烦恼,因为在 PHP 脚本中设置 session.gc_maxlifetime 是无效的,Plesk 有自己的垃圾回收脚本从 cron 中运行。
我在下面的链接中找到了解决方案,将 cron 作业从 hourly 改为 daily 可以避免这个问题,然后上面的最佳答案就可以使用:
mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/
https://websavers.ca/plesk-php-sessions-timing-earlier-expected
$_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()
销毁会话可能是更好的选择,以防恶意客户端或机器人。
不行。 如果您无法访问php.ini,就不能保证更改会产生任何效果。
我怀疑您并不需要延长会话时间。
目前的超时时间非常合理,没有理由要延长它。
SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
- Your Common Sense您可以使用ini_set()
从您的PHP代码中覆盖php.ini中的值。
session.gc_maxlifetime
不是控制会话生命周期的设置。如果将session.gc_divisor
设置为1,它可以被强制用于控制会话生命周期,但这样做非常糟糕。 - Jongc_maxlifetime
设置会话数据在多长时间后可以进行垃圾回收,如果GC在经过这么长时间后发生,会话数据将被销毁(使用默认设置时,这与会话过期相同)。但是,每次会话启动时都会以概率触发GC,因此不能保证会话实际上会过期 - 您可以绘制概率曲线与时间的关系,但它看起来不像砖墙。这只是冰山一角;请参见https://dev59.com/1XRB5IYBdhLWcg3wxZ1K - Jon