提问人:Megan Caza 提问时间:11/7/2023 最后编辑:Salman AMegan Caza 更新时间:11/21/2023 访问量:151
会话在使用 session_regenerate_id 后死亡(true)
Session dying after using session_regenerate_id(true)
问:
我遵循了一个教程,无论我检查多少次此代码,我都无法让它长期工作。登录后,会话开始,但在应重置的设置间隔时间()后,会话将被销毁,用户注销。60* 30
我缩短了测试时间,将时间设置为每 30 秒刷新一次页面。60 * 3
该会话也在 3 分钟后死亡,尽管该页面是唯一刷新的页面,并且要求位于页面顶部(require_once 'includes/config_session.inc.php';
)
如何防止会话死亡并在使用后保持用户登录状态?session_regenerate_id(true)
这是我的 config_session.inc 的代码.php
<?php
ini_set('session.use_only_cookies', 1);
ini_set('session.use_strict_mode', 1);
session_set_cookie_params([
'lifetime' => 1800,
'domain' => 'www.snoozelings.com',
'path' => '/',
'secure' => true,
'httponly' => true
]);
session_start();
if (isset($_SESSION["user_id"])) {
if (!isset($_SESSION['last_regeneration'])) {
regenerate_session_id_loggedin();
} else {
$interval = 60 * 30;
if (time() - $_SESSION['last_regeneration'] >= $interval) {
regenerate_session_id_loggedin();
}
}
} else {
if (!isset($_SESSION['last_regeneration'])) {
regenerate_session_id();
} else {
$interval = 60 * 30;
if (time() - $_SESSION['last_regeneration'] >= $interval) {
regenerate_session_id();
}
}
}
function regenerate_session_id() {
session_regenerate_id(true);
$_SESSION['last_regeneration'] = time();
}
function regenerate_session_id_loggedin() {
session_regenerate_id(true);
$userID = $_SESSION["user_id"];
$newSessionId = session_create_id();
$sessionId = $newSessionId . "_" . $userID;
session_id($sessionId);
$_SESSION['last_regeneration'] = time();
}
答:
这是由于 PHP 的会话 COOKIE 在每次请求时或当我们调用函数时没有刷新。session_start
当我们第一次调用会话 时,会话 COOKIE 被创建一次,然后保持原样。session_start
这背后的逻辑是,默认情况下,param 的值为 ,这意味着请参阅:PHP 文档>会话配置。session.cookie_lifetime
0
"until the browser is closed."
您还可以阅读以下错误报告,其中确切地描述了此“问题”。要注意的一个关键点是,如果在浏览器关闭(或会话结束)时未清除会话 cookie,则当用户(相同或更糟)在同一页面上重新打开浏览器时,它将保留会话!
话虽如此,您可以在需要时手动更新会话 COOKIE。在函数中的示例代码中,您希望为登录用户保留会话。regenerate_session_id_loggedin()
因此,您可以在函数末尾添加以下内容:
/**
* Renew the time left until this session times out.
* If we do not do this, the session will time out based on the
* time when it was created rather than when it was last used.
* @see https://www.php.net/manual/en/function.session-set-cookie-params.php#100657
*/
if(isset($_COOKIE[session_name()])) {
setcookie(
session_name(),
session_id(),
time() + (60 * 30),
'/',
'www.snoozelings.com',
true,
true
);
}
这应该可以解决超时问题。
作为旁注(与超时无关),在session_regenerate_id的文档中,您可能还需要更改创建自定义会话 ID 的逻辑。上面的文档页面中有一个示例,建议执行以下步骤:
- 通过以下方式保存并关闭当前会话
session_commit()
- 通过以下方式设置新的会话 ID
session_id('YOUR_CUSTOM_ID')
- 禁用
use_strict_mode
- 通过 启动会话,该会话将具有新定义的 ID。
session_start()
- 使
use_strict_mode
这样:
// inside of your regenerate_session_id_loggedin
$newSessionId = session_create_id();
// Customize session ID for current USER.
$sessionId = $newSessionId . "_" . $userID;
// Write and close current session;
session_commit();
// Start session with new session ID
session_id($sessionId);
ini_set('session.use_strict_mode', 0);
session_start();
ini_set('session.use_strict_mode', 1);
// ... rest of your code.
另请注意,调用 which 续订会话 ID,然后创建并分配一个新 ID。
此外,无论其登录状态如何,都会为所有用户调用 the,这是您可能想要也可能不希望看到的。session_regenerate_id
session_regenerate_id
第二点(这也与超时无关):你可以对代码进行一些重构,以免重复某些逻辑。例如:
<?php
ini_set('session.use_only_cookies', 1);
ini_set('session.use_strict_mode', 1);
// Init Session config vars.
$sessionCookieLifetime = 60 * 30;
$mySessionCookieParams = [
'lifetime' => $sessionCookieLifetime,
'domain' => 'www.snoozelings.com',
'path' => '/',
'secure' => true,
'httponly' => true
];
session_set_cookie_params($mySessionCookieParams);
session_start();
if ( ! isset($_SESSION['last_regeneration']) ) {
regenerateSessionByUserStatus();
} else {
if (time() - $_SESSION['last_regeneration'] >= $sessionCookieLifetime) {
regenerateSessionByUserStatus();
}
}
function regenerateSessionByUserStatus() {
session_regenerate_id(true);
if (isset($_SESSION["user_id"])) {
$userID = $_SESSION["user_id"];
$newSessionId = session_create_id();
$sessionId = $newSessionId . "_" . $userID;
session_id($sessionId);
/**
* Renew the time left until this session times out.
* If we do not do this, the session will time out based on the
* time when it was created rather than when it was last used.
* @see https://www.php.net/manual/en/function.session-set-cookie-params.php#100657
*/
if(isset($_COOKIE[session_name()])) {
setcookie(
session_name(),
session_id(),
time() + $sessionCookieLifetime,
$mySessionCookieParams['path'],
$mySessionCookieParams['domain'],
$mySessionCookieParams['secure'],
$mySessionCookieParams['httponly']
);
}
}
$_SESSION['last_regeneration'] = time();
}
评论
<?php phpinfo();