会话过期后自动注销用户
Automagically logout user after session expires
我遇到了一个问题:在会话过期时自动 注销用户。我正在尝试模仿 SugarCRM 中的行为,一旦您的会话过期,就会有一个警报告诉您您已经注销,并且您将重定向到登录屏幕以重新登录。 无论有没有用户交互都会发生这种情况。
到目前为止,在yii2中,用户必须事先执行请求。会话可能已过期,但页面会一直保留到用户尝试执行新请求为止。在处理此请求时,应用程序可以使用控制器过滤器或 beforeAction()
挂钩进行检查。
我想在他们的会话过期后立即将他们重定向到登录页面。我如何自动执行此操作?
SugarCRM 必须通过某些 javascript(ajax 请求)定期检查会话,检查 Chrome 中 DevTool 中“网络”选项卡上的 XHR,您将在之前看到此调用注销警报。
这是一个非常简单的示例,说明您如何使用 JavaScript 定期调用 ajax 来检查用户是否仍处于登录状态。这假定您的后端 PHP 脚本returns {"loggedin":true/false} 的特定格式并且您的 ajax() 函数采用我在下面实际使用的三个参数,因此您必须修改语法以使其适合您的需要并适应您实际使用的任何 ajax 函数的要求(如 jQuery、原生 JS,无论您使用什么)...
var checkLogin = function() {
//// presumes that you have some ajax function going
//// with something like ajax(method,url,callback)
//// and that it's returning something like {loggedin:true/false}
ajax("GET", "some-check-login-script.php", function(json) {
var data = JSON.parse(json);
if (!data.loggedin) {
runSomeFunctionToAlertOrRefreshOrWhatever();
clearInterval(logincheckinterval);
}
});
}
var logincheckinterval = setInterval(checkLogin, 5000);
您只需要修改语法以满足特定框架对进行 ajax 调用的要求,然后相应地修改其余部分以执行您希望它执行的任何操作(警报、提示、自定义对话框,无论什么)一旦它从返回的数据中捕获到 'false' 值。
希望对您有所帮助。
以上所有答案均有效,除了...您必须以其他方式实现会话。
对服务器的任何调用基本上都会重置您的正常会话。通过每 x 秒检查一次您是否仍处于登录状态,您将做到这一点,因此您永远不会注销。在每次检查呼叫时,您的会话到期时间都会重置。
所以这必须与您将修改会话处理方式的事实相结合。您希望在实际页面导航上重置会话计时器,而不是像 PHP 默认处理它。
我之前在我的 Yii2 应用程序上有同样的任务,这就是我所做的。
使用 js setInterval 创建了小部件并将其插入到主布局中。
class UserTimeout extends Widget
{
public $checkUrl = ['/index/check-user-timeout'];
public $redirectUrl = ['/index/login'];
public function run()
{
$timeout = \Yii::$app->user->authTimeout * 1000 + 5000; // milliseconds
$url = Url::to($this->checkUrl);
$redirect = Url::to($this->redirectUrl);
$this->view->registerJs("
function checkUserTimeout() {
$.post('{$url}', function(data){
if(data){
document.location = '{$redirect}';
}
});
}
setInterval(checkUserTimeout, $timeout);
");
}
}
关闭了用户组件中的自动登录:
'components' => [
'user' => [
'enableAutoLogin' => false,
'authTimeout' => 60 * 60,
坦率地说,我是通过事件 yii\web\Application 'beforeRequest' 实现的,因为我需要通过 cookie 自动登录才能为其他请求启用。
进行了 'index/check-user-timeout' 操作:
public function actionUserTimeout()
{
$expire = time() - Yii::$app->session->get('__expire');
if ($expire >= 0) {
Yii::$app->session->setFlash('warning', Yii::t('common', 'auth_timeout'));
return true;
}
return false;
}
重要的是避免在此操作之前检查用户身份(不要在它的 beforeAction() 或相关事件中执行类似的操作:"if (Yii::$app->user->isGuest)")- 这将刷新会话过期值。
用户组件应如下所示:
'user' => [
'identityClass' => 'app\models\User',
'authTimeout' => 300,
'enableAutoLogin' => false, // !important to set this
],
如果您还想即时设置authTimeout
我遇到了同样的问题。我想即时设置用户的 authTimeout
,我还希望用户在时间到期后自动注销并重定向到登录屏幕(无论是否有用户交互)。我就是这样做的。我已经在 config/web.php
中将用户 authTimeout
和会话超时设置为相同的值,并且我还注册了一个新的元标记,它将在会话过期 5 秒后刷新页面,因此它会自动重定向到登录屏幕。
在config/web.php:
'on beforeRequest' => function ($event) {
$user = Yii::$app->user;
if (!$user->isGuest) {
if (!empty(Yii::$app->params['settings']['security_timeout'])) {
$user->authTimeout = intval(Yii::$app->params['settings']['security_timeout']);
Yii::$app->session->set($user->authTimeoutParam, time() + $user->authTimeout);
Yii::$app->view->registerMetaTag(['http-equiv' => 'refresh', 'content' => $user->authTimeout + 5]);
}
}
},
当然,如果你不想即时设置 authTimeout
就简单多了。
如果不需要即时设置authTimeout
只需在您的布局或产品中的任何位置注册元标记,并将刷新时间设置为比 authTimeout
稍微长一点。
Yii::$app->view->registerMetaTag(['http-equiv' => 'refresh', 'content' => Yii::$app->user->authTimeout + 5]);
我遇到了一个问题:在会话过期时自动 注销用户。我正在尝试模仿 SugarCRM 中的行为,一旦您的会话过期,就会有一个警报告诉您您已经注销,并且您将重定向到登录屏幕以重新登录。 无论有没有用户交互都会发生这种情况。
到目前为止,在yii2中,用户必须事先执行请求。会话可能已过期,但页面会一直保留到用户尝试执行新请求为止。在处理此请求时,应用程序可以使用控制器过滤器或 beforeAction()
挂钩进行检查。
我想在他们的会话过期后立即将他们重定向到登录页面。我如何自动执行此操作?
SugarCRM 必须通过某些 javascript(ajax 请求)定期检查会话,检查 Chrome 中 DevTool 中“网络”选项卡上的 XHR,您将在之前看到此调用注销警报。
这是一个非常简单的示例,说明您如何使用 JavaScript 定期调用 ajax 来检查用户是否仍处于登录状态。这假定您的后端 PHP 脚本returns {"loggedin":true/false} 的特定格式并且您的 ajax() 函数采用我在下面实际使用的三个参数,因此您必须修改语法以使其适合您的需要并适应您实际使用的任何 ajax 函数的要求(如 jQuery、原生 JS,无论您使用什么)...
var checkLogin = function() {
//// presumes that you have some ajax function going
//// with something like ajax(method,url,callback)
//// and that it's returning something like {loggedin:true/false}
ajax("GET", "some-check-login-script.php", function(json) {
var data = JSON.parse(json);
if (!data.loggedin) {
runSomeFunctionToAlertOrRefreshOrWhatever();
clearInterval(logincheckinterval);
}
});
}
var logincheckinterval = setInterval(checkLogin, 5000);
您只需要修改语法以满足特定框架对进行 ajax 调用的要求,然后相应地修改其余部分以执行您希望它执行的任何操作(警报、提示、自定义对话框,无论什么)一旦它从返回的数据中捕获到 'false' 值。
希望对您有所帮助。
以上所有答案均有效,除了...您必须以其他方式实现会话。
对服务器的任何调用基本上都会重置您的正常会话。通过每 x 秒检查一次您是否仍处于登录状态,您将做到这一点,因此您永远不会注销。在每次检查呼叫时,您的会话到期时间都会重置。
所以这必须与您将修改会话处理方式的事实相结合。您希望在实际页面导航上重置会话计时器,而不是像 PHP 默认处理它。
我之前在我的 Yii2 应用程序上有同样的任务,这就是我所做的。
使用 js setInterval 创建了小部件并将其插入到主布局中。
class UserTimeout extends Widget { public $checkUrl = ['/index/check-user-timeout']; public $redirectUrl = ['/index/login'];
}public function run() { $timeout = \Yii::$app->user->authTimeout * 1000 + 5000; // milliseconds $url = Url::to($this->checkUrl); $redirect = Url::to($this->redirectUrl); $this->view->registerJs(" function checkUserTimeout() { $.post('{$url}', function(data){ if(data){ document.location = '{$redirect}'; } }); } setInterval(checkUserTimeout, $timeout); "); }
关闭了用户组件中的自动登录:
'components' => [ 'user' => [ 'enableAutoLogin' => false, 'authTimeout' => 60 * 60,
坦率地说,我是通过事件 yii\web\Application 'beforeRequest' 实现的,因为我需要通过 cookie 自动登录才能为其他请求启用。
进行了 'index/check-user-timeout' 操作:
public function actionUserTimeout() { $expire = time() - Yii::$app->session->get('__expire'); if ($expire >= 0) { Yii::$app->session->setFlash('warning', Yii::t('common', 'auth_timeout')); return true; } return false; }
重要的是避免在此操作之前检查用户身份(不要在它的 beforeAction() 或相关事件中执行类似的操作:"if (Yii::$app->user->isGuest)")- 这将刷新会话过期值。
用户组件应如下所示:
'user' => [
'identityClass' => 'app\models\User',
'authTimeout' => 300,
'enableAutoLogin' => false, // !important to set this
],
如果您还想即时设置authTimeout
我遇到了同样的问题。我想即时设置用户的 authTimeout
,我还希望用户在时间到期后自动注销并重定向到登录屏幕(无论是否有用户交互)。我就是这样做的。我已经在 config/web.php
中将用户 authTimeout
和会话超时设置为相同的值,并且我还注册了一个新的元标记,它将在会话过期 5 秒后刷新页面,因此它会自动重定向到登录屏幕。
在config/web.php:
'on beforeRequest' => function ($event) {
$user = Yii::$app->user;
if (!$user->isGuest) {
if (!empty(Yii::$app->params['settings']['security_timeout'])) {
$user->authTimeout = intval(Yii::$app->params['settings']['security_timeout']);
Yii::$app->session->set($user->authTimeoutParam, time() + $user->authTimeout);
Yii::$app->view->registerMetaTag(['http-equiv' => 'refresh', 'content' => $user->authTimeout + 5]);
}
}
},
当然,如果你不想即时设置 authTimeout
就简单多了。
如果不需要即时设置authTimeout
只需在您的布局或产品中的任何位置注册元标记,并将刷新时间设置为比 authTimeout
稍微长一点。
Yii::$app->view->registerMetaTag(['http-equiv' => 'refresh', 'content' => Yii::$app->user->authTimeout + 5]);