Yii session timeout not working - session

same as title, in my config:
'session' => array(
'class'=>'CHttpSession',
'timeout'=> 1200,
'autoStart'=>true,
),
in my code:
$ssKey = 'MY_SS_KEY';
if (isset(Yii::app()->session[$ssKey])) {
$this->jobWithSession();
} else {
$this->jobWithNotSession();
Yii::app()->session[$ssKey] = 'ok';
}
first time, it call function jobWithNotSession(), but after over 1200s (20 minute), it still call function jobWithNotSession, what's wrong? somebody can help me?

In order to make Yii session timeout to work, you should do the following:
In protected/config/main.php:
'components'=>array(
'session' => array(
'class' => 'CDbHttpSession', //Set class to CDbHttpSession
'timeout' => 1800, //Any time, in seconds
),
),
1800 is the time, in seconds, during which your time session will be active.
It is algo important to set the class to CDbHttpSession.

You are using the wrong functionality here. The session timeout is only applicable when the php garbage collector is getting called, which is far from every page-view. It has something to do with the gc_probability-setting. So that's not what you want to use. As long as it doesn't run, the session still exists (even though expired) and the user remains logged in.
What you do want is to "remove" the autoLogin cookie, which you can do by controlling the duration of it.
So basically what you need to change is the duration parameter of the CWebUser::login()-function.

Related

Does Laravel log users off automatically after an interval?

I'm new to Laravel and am using Laravel 6. I am working on an app that uses the default authentication for Laravel. I registered myself three times with three different email addresses for testing purposes. I'm finding that after a few hours, I'm logged off and have to log back in again even though I did not click on the logoff option.
Am I correct in assuming there is some kind of default timeout for IDs in Laravel? If so, how to change the interval or disable it altogether?
If that isn't the issue, what could account for me being logged out?
Laravel authentication uses session driver for web guard as default. You can check your default web guard's driver on config/auth.php.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
//...
],
The Laravel session's lifetime is 120 minutes by default, You can also check this default value on config/session.php as lifetime property.
'lifetime' => env('SESSION_LIFETIME', 120),
So you'll be logged off automatically (i.e your session expires) after 2 hours by default.
If you want to stay login for a long time, you have 2 options:
Select the "remember me" option when logging into your application (Recommended).
Set a large value (e.g 10 years or so) for session's lifetime on local .env file. It's not recommended on production environment, because not only authenticated users but also all visitors (including guest, bots etc.) would have a longtime session.
SESSION_LIFETIME=5256000 // 10 years
If you check CookieSessionHandler::write and CookieSessionHandler::read:
//write
/**
* {#inheritdoc}
*/
public function write($sessionId, $data)
{
$this->cookie->queue($sessionId, json_encode([
'data' => $data,
'expires' => $this->availableAt($this->minutes * 60),
]), $this->minutes);
return true;
}
//read
/**
* {#inheritdoc}
*/
public function read($sessionId)
{
$value = $this->request->cookies->get($sessionId) ?: '';
if (! is_null($decoded = json_decode($value, true)) && is_array($decoded)) {
if (isset($decoded['expires']) && $this->currentTime() <= $decoded['expires']) {
return $decoded['data'];
}
}
return '';
}
you can see that there must be some value of time to compare with current time value. Otherwise an empty string is returned and session is being invalidated. Best way you can do is to set config value to something really large (e.g. 35791394 [~68 years in minutes]) This is fail safe for 32-bit systems because it is 2147483640 which is less than signed 32-bit MAX_INT value 2147483647, just in case. Even if sometimes in future Laravel rewrite session lifetime to use seconds instead of minutes this will last for more than a year.
Another SO answer.

The sessions are dying on redirect

The sessions are no longer working on redirect, if i set a session with session([ 'key' => 'value' ]); is working on the same page, but if i set the session in controller, after redirect is NULL, also, when i redirect, the values passed ->with(array) are NULL:
return redirect()->route('account.login', ['subdomain' => 'account'])->with(
[
'request-tfa' => true,
'requested-email' => $validatedData['email'],
'requested-password' => encrypt($validatedData['password'])
]);
When i get the value using Session::get('request-tfa') is NULL, until now, this worked perfectly.
Do anyone have any idea how to fix it?
Should i try to use a database as session storage? but i don't know how to setup the database to store the sessions.
EDIT: I changed the session driver to database and is still not working, but the sessions are stored.
And even \Auth::attempt is not working, like, if i use:
if(\Auth::attempt(['email' => $validatedData['email'], 'password' => $validatedData['password']]))
{
return \Auth::id();
}
it working, but if i have return redirect i am guest again.
EDIT X2
Well, i changed my virtual host domain and restarted my pc and now is working...
If you want to have a session after redirect you should use:
session()->put('something')

Possible ajax call to result in extreme load times after redirects?

I have the following senario
Page A is being loaded and fires up 3 ajax calls, they take some time because they are working on getting a lot of data, though nothing the server can't handle. Now the user is redirecting to page B before the ajax calls have finished. I know they will continue running on the background, but could this possible cause dramatic loading times? There is no sql overheat, server processor is only using around 10% of it's limits. Yet loading times can differ from 1-2 seconds all the way to 50+ seconds.
Is it possible that this is being caused by the previous, yet running ajax calls and that the browser is somehow still having a connection with these calls and awaits response before it will load the next page??
Based on your answer in the comment section i try to explain it and provide a solution for this - because i ran a ton of times in this issue - although you write that your ajax calls are not using the session library - check out if you start it anyway.
PHP writes session data to a file by default. If a request starts it starts the session. This session file is locked. What this means is that if your web page makes a ton of requests to PHP scripts, e.g. for loading content via Ajax, each request locks the session and prevents the other requests to complete.
What we did in order to prevent situations like that is the following:
in your /application/config/hooks.php
$hook['pre_controller'][] = array(
"class" => "AppSessionInterceptor",
"function" => "initialize",
"filename" => "AppSessionInterceptor.php",
"filepath" => "hooks"
);
and after that create a hook called AppSessionInterceptor
class AppSessionInterceptor
{
private $ci;
public function __construct()
{
$this->ci = &get_instance();
}
public function initialize()
{
//some doings
$this->closeSession();
}
private function closeSession()
{
$blnSessWriteClose = true;
$arrStopSessionFromWriteClose = array(
$this->ci->uri->segment(1) => array("logout","login"),
$this->ci->uri->segment(2) => array("logout","login"),
$this->ci->input->get("blnWriteSession") => array(1)
);
foreach($arrStopSessionFromWriteClose AS $key => $arrValue)
{
if (in_array($key, $arrValue))
{
$blnSessWriteClose = false;
break;
}
}
if ($blnSessWriteClose) session_write_close();
}
}
This closes the session before anything else is called.
Keep in mind that if you close a session - you are able to read the data but can't write it anymore.

PHP: storing closures in session breaks session

Update: solved
I finally figured out my problem (I think). I'm pretty sure the issue is that closures cannot be serialized, which means they cannot be stored in the session. The next issue then is that PHP was not returning a very useful error, and was breaking in an unexpected way, instead of just telling me that I couldn't serialize a closure.
I store my session data in a mysql database. I've had that part of my application in place and working well for quite a while. Today I tried to store a closure (i.e. anonymous function) in the session and that broke my otherwise very well behaved sessions.
My session management is handled by an object, which automatically calls session_write_close() when PHP attempts to destroy the object. I did this so that because otherwise, by the time PHP tries to close the session, my database connection (a mysqli object) has already been destroyed.
I take over the session handling like this:
// set the session save handler
session_set_save_handler(
array( $this, '_open' ),
array( $this, '_close' ),
array( $this, '_read' ),
array( $this, '_write' ),
array( $this, '_destroy' ),
array( $this, '_clean' )
);
which is pretty standard. The part that handles session closing is this:
public function __destruct()
{
// this variable will only be destroyed when the script is closing
// at this point it is safe to close the session
// if we wait for php to close the session then we will
// have lost the database connection, so we do it now
session_write_close();
}
// write session data
public function _write( $sid, $data )
{
// run query to write to database
$now = NOW;
$stmt = $this->mysqli->prepare( "REPLACE INTO $this->table (sid,time,data) VALUES (?,?,?)" );
$stmt->bind_param( 'sis', $sid, $now, $data );
// execute
$success = $stmt->execute();
// close
$stmt->close();
// and return
return $success;
}
// close session store
public function _close()
{
// close the database connection
$this->mysqli->close();
return true;
}
A couple print functions reveal that normally this works just as you would think: the __destruct() function is called, which calls session_write_close(), which is immediately followed up by calls to _write() and _close(). However, the moment I store a closure to the session:
$test = function($name)
{
print "Hello $name";
};
$_SESSION['test'] = $test;
Everything breaks. __destruct() is called as before, but execution never reaches the _write() or _close() functions. Instead I get these messages:
Warning: session_write_close() [function.session-write-close]: Failed to write session data (user). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in /var/www/vhosts/ambida.com/httpdocs/includes/core/session_handler.php on line 48
Fatal error: Exception thrown without a stack frame in Unknown on line 0
Which really makes no sense. It looks like it has reverted back to the default session handler, which would of course fail because the tmp file was never opened (since my function took over opening the session). I don't understand why storing a closure in the session would cause such a revert to happen, or why this is breaking in general. Any help would be appreciated.
This can now be achieved by using the SuperClosurefrom Jeremy Lindblom. The Package can be found on his github : https://github.com/jeremeamia/super_closure

Session data gone after redirect in CI

i need your help.
I used the session to record the user selected business type in CI. For example,$this->ci->session->set_userdata('biztype','food'). When user login,it works ok. However, once the user logout, session will be destroyed in the function logout().So i set the userdata again in the function logout().You can view the code below:
function logout()
{
$biztype = $this->ci->session->userdata('biztype');
$this->delete_autologin();
$this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
$this->ci->session->sess_destroy();
$this->ci->session->set_userdata('biztype',$biztype);
//echo $this->ci->session->userdata('biztype'); //here, i can get biztype that i want
}
However,when i logout and redirect to homepage, i cant get the userdata('biztype') and my session_id have changed.
Thanks for the help.
This is straight from CodeIgniter User Guide:
Destroying a Session
To clear the current session:
$this->session->sess_destroy();
Note: This function should be the last one called, and even flash
variables will no longer be available. If you only want some items
destroyed and not all, use unset_userdata().
So no, you cannot destroy a session then add user_data to it, you need to reload / redirect then once the NEW session is established add data.
Try using cookies for peristance, or use the mentioned unset_userdata() fn.
$this->session->sess_destroy() ;
This function should be called only at the end of the execution. For unsetting data (as you're trying to do) it's better to use unset_userdata method. See how you should implement that:
$unset_items = array('user_id' => '', 'username' => '', 'status' => '') ;
$this->ci->session->unset_userdata( $unset_items ) ;
$email = "abc#gmail.com";
///set the session
use the set_userdata function and include the session library
$this->load->library('session');
$this->session->set_userdata('session name',Value);
i.e.
$this->session->set_userdata('email', $email);
//unset the session
$this->session->unset_userdata('session name');
i.e.
$this->session->unset_userdata('email');

Resources