我想在php中延长会话超时
我知道可以通过修改php.ini文件来实现。但我无权访问。
那么有可能只用php代码来做到吗?
我想在php中延长会话超时
我知道可以通过修改php.ini文件来实现。但我无权访问。
那么有可能只用php代码来做到吗?
Answers:
如果需要严格的保证,会话超时是必须在代码中实现的概念。这是唯一的办法,你可以绝对肯定的是,没有永远的会话将不活动的X分钟后存活。
如果稍微放宽此要求是可以接受的,并且可以设置下限而不是严格的持续时间,则可以轻松完成此操作,而无需编写自定义逻辑。
如果您的会话与饼干(他们可能是)来实现,并且如果客户端是没有恶意的,你可以设定一个上限通过调整某些参数绑定在会话持续时间。如果您将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对您很重要的情况下,必须注意session_regenerate_id
在需要时使用它们重新生成它们。
session_start()
(否则完全无效),并且仅当您始终之前调用这两个选项session_start
(否则gc_maxlifetime
才有可能影响当前打开的所有会话,而session_set_cookie_params
只能影响以开头的新会话)当前请求)。
如果使用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的生存期对于您的主机来说已经足够了,但是,如果您想要一个即使您切换主机也能可靠运行的解决方案,则必须使用其他选择。
可用的替代方法包括:
按照PHP中的指定,在PHP中设置其他会话(保存)处理程序以将您的会话保存到其他目录或数据库中:自定义会话处理程序(PHP手册),以便cron作业不会到达它,而只有PHP可以内部垃圾收集发生。此选项可能可以利用它ini_set()
来设置session.gc_maxlifetime,但我更喜欢忽略回调中的maxlifetime参数,gc()
并自行确定最大寿命。
完全无需考虑PHP内部会话处理,并实现自己的会话管理。此方法有两个主要缺点:您将需要自己的全局会话变量,因此您将失去$_SESSION
超全局变量的优势,并且它需要更多的代码,因此存在更多的漏洞和安全漏洞的机会。最重要的是,会话标识符应该从加密安全的随机数或伪随机数中生成,以避免会话ID的可预测性(导致可能的会话劫持),而使用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)更复杂;基本上,您必须自己重新实现所有会话功能。我不会在这里详细介绍。
php.ini
您的实际选择,将受到严格限制。
/usr/lib/php5/maxlifetime
无法计算24分钟以下的值。因此,您不能将会话超时设置为低于此值。
为使用Plesk的任何人添加注释时遇到上述任何问题,因为这使我发疯,在您的PHP脚本中设置session.gc_maxlifetime无效,因为Plesk拥有从cron运行的自己的垃圾收集脚本。
我使用了下面链接上发布的解决方案,将cron作业从每小时移到每天,以避免出现此问题,那么上面的最佳答案应该可以起作用:
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_value session.save_path“ folderA / sessionsA”为添加的域设置不同的保存会话目录。
因此,请在您的根服务器上创建一个文件夹,而不要在public_html中创建一个文件夹,并且不要从外部进行公开访问。对于我的cpanel /服务器,该文件夹的权限为0700,工作正常。请尝试...
PHP代码 =
#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);
ini_set('session.cache_expire', 57600);
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
否。如果您无权访问php.ini,则不能保证所做的更改会产生任何影响。
我怀疑您是否需要延长会话时间。
目前,它的超时很合理,没有理由延长它。
SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
您可以使用来从PHP代码覆盖php.ini中的值ini_set()
。
session.gc_maxlifetime
不是控制会话生存期的设置。如果将设置session.gc_divisor
为1
,则可能会像这样工作,这太糟糕了,但这太可怕了。
gc_maxlifetime
设置会话数据有资格进行垃圾回收的时间间隔-如果在经过了这么长的时间后发生GC,则会话数据将被销毁(默认设置与会话过期相同)。但是GC会在每次会话开始时随机触发,因此不能保证该会话实际上会到期-您可以绘制概率与时间的关系曲线,但看起来不会像是一堵砖墙。那只是冰山一角。参见stackoverflow.com/questions/520237/…–