Logout automatically after session ends
I'm having a problem: Automatically log out when the session expires. I am trying to simulate the behavior in SugarCRM, where once your session has expired, an alert tells you that you are logged out and you redirecrec at the login screen to re-login. This happens with or without user interaction.
Until now in yii2, the user must complete the request in advance. The session may have expired, but the page persists until the user tries to make a new request. While processing this request, the application can then check for use of controller filters or beforeAction()
hooks.
I want to redirect them to the login page as soon as their session expires. How to do it automatically?
source to share
All of the above answers are valid except ... you need to complete the session in a different way.
Any call to the server will basically reset your normal session. By checking every x seconds you are still logging, you will ensure that you never log out. On every control call, your session expiration time will be reset.
So this must be combined with the fact that you will be changing the way the session is handled. You want the actual page navigation to reset the session timer, not how PHP handles it by default.
source to share
The custom component should look something like this:
'user' => [
'identityClass' => 'app\models\User',
'authTimeout' => 300,
'enableAutoLogin' => false, // !important to set this
],
If you also want to install authTimeout
on the fly
I faced the same problem. I wanted to set the user authTimeout
on the fly, and I also wanted the user to automatically log out and be redirected to the login screen after a timeout (whether it was a user interaction or not). This is how I did it. I set user authTimeout
and session timeout to the same value in config/web.php
and I also registered a new meta tag that will refresh the page 5 seconds after the session ends, so it will automatically redirect to the login screen.
In 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]);
}
}
},
Of course, this is much easier if you don't want to install authTimeout
on the fly.
If you don't need to install authTimeout
on the fly
Just register the meta tag in your layout or anywhere in the product and set the refresh time slightly higher than authTimeout
.
Yii::$app->view->registerMetaTag(['http-equiv' => 'refresh', 'content' => Yii::$app->user->authTimeout + 5]);
source to share
Here is a very simplified example of how you can use JavaScript to make periodic ajax calls to check if the user is still logged in. This assumes that your PHP backend script is returning a certain format {"loggedin": true / false} and that your ajax () function takes three parameters, which I am actually using below, so you will need to change the syntax to do this according to your needs and meet the requirements of whatever ajax function you actually use (like in jQuery, native JS, whatever you use) ...
var checkLogin = function() {
//// presumes that you have some ajax function going
//// with something like ajax(method,url,callback)
//// and that it 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);
You just need to change the syntax to suit your specific infrastructure requirements for making that ajax call, and then modify the rest accordingly to do what you want (alert, prompt, custom dialog, whatever) catches "false" value back from the returned data.
Hope it helps.
source to share
I had the same task in my Yii2 application and this is what I did.
-
Created a widget with js setInterval and inserted into the main layout.
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); "); }
-
Disable autoloading in custom component:
'components' => [ 'user' => [ 'enableAutoLogin' => false, 'authTimeout' => 60 * 60,
To be honest, I did it with the yii \ web \ Application 'beforeRequest' event because I needed to autologize the cookie for other requests.
-
Action '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; }
It is important not to check the user's identity before this action (do not make beforeAction () or related events in it: "if (Yii :: $ app-> user-> isGuest)") - this will update the session end value.
source to share