PHP session logs out before session cookie expires - php

I have set up cookie lifetime to last a complete day, but after 15-20 mins of idle time, I get logged out anyways. The strangest thing is that everything runs fine on localhost, but when I took my website live, I started experiencing this problem with the same exact code.
I read on stackoverflow that it could be related to session.gc_maxlifetime, so I have even edited that on the .htaccess level. I have changed it from 1440 to 86400, but the problem still persists.
Here is the rundown of my code.
When a user logs in, I check if the user already has a cookie named 'AUTHID'. If the user does, I first delete it.
if (isset($_COOKIE['AUTHID'])) {
unset($_COOKIE['AUTHID']);
setcookie('AUTHID', null, -1, '/');
}
After that, depending on if the user selected Remember Me option, I set the cookie lifetime value, and it creates a cookie that I can see in Chrome Settings with absolutely correct expiration time.
session_name('AUTHID');
ini_set('session.cookie_httponly', 1);
if(isset($_POST['remember-me'])) {
ini_set('session.gc_maxlifetime', 604800);
session_set_cookie_params(604800,"/");
} else {
ini_set('session.gc_maxlifetime', 86400);
session_set_cookie_params(86400,"/");
}
session_start();
Lastly, I have a php function to check if the user is logged in on every single page:
$rel_url = "$_SERVER[REQUEST_URI]";
session_name('AUTHID');
session_start();
if(!isset($_SESSION['user_id'])) {
if (strpos($rel_url, 'login=success') !== false) {
header('Location: index.php');
}
header('Location: login-with-bg.php?access-denied=logged-out');
exit();
}
This works perfectly fine on my localhost, but when I uploaded this code on my hosting server, even though the cookie is still being created with correct expiration date, but if my browser is idle for 15-20 mins, my session gets timed out.
EDIT: from an article, I got an idea of making AJAX calls every 10 mins or so, and that works when the browser is open. However, I need a complete method that works even if the browser is closed.
EDIT2: The AJAX code that I have for keeping the session alive:
function keep_alive() {
$.get('index.php',null)
}
keep_alive_interval = setInterval(keep_alive, 600000)

A few notes:
Session and ajax is a tricky thing. Be sure to close your session when doing an ajax call so it writes changes to your session. (register_shutdown_function("session_write_close");)
In this case there is no real use in changing the sessionname (default will do).
The AUTHID cookie stores your session_id which corresponds to your session. This has to be set also. No need to manually set the cookie
This is working for me on the server but not on local machines
if ($_SERVER['SERVER_ADDR'] != '127.0.0.1'){ // Only use custom session on server. use default settings on local machine
register_shutdown_function("session_write_close"); // write your changes done with ajax before your session opens again
// some security settings
ini_set("session.use_strict_mode", 1);
ini_set("session.cookie_httponly", 1);
ini_set("session.cookie_secure", 1);
ini_set("session.use_only_cookies", 1);
ini_set("session.gc_maxlifetime",60 * 60 * 24 * 14); // 2 weeks
session_set_cookie_params(60 * 60 * 24 * 14,"/",".yourdomain.com"); // 2 weeks
session_name("AUTHID");
if(isset($_COOKIE['AUTHID'])){
session_id($_COOKIE['AUTHID']);
}
}
session_start();

Related

How to increase login session timeout?

Question:
How to increase login session timeout?
Situation:
I have a login script in PHP that connects to a MYSQL database. Right now a login session lasts for about 24 hours. But I want this to be 2 weeks. So I want my users to have to login again after 2 weeks. Again, right now a user has to re-login after about 24 hours. I haven't been able to measure this precisely. But I always have to re-login the next day. What I also should mention is that I have closed the browser and even restarted the computer to see if I'm still logged in the same day. And yes, the login session is still intact. But the next day this session is gone.
Code used but did not work:
ini_set('session.gc_maxlifetime', 1209600);
session_set_cookie_params(1209600);
session_start();
I noticed when looking at my php.ini file that mysqlnd read timeout lasts for exactly 24 hours. So I also added the following code to the code above:
ini_set('mysqlnd.net_read_timeout', 1209600);
But this all doesn't make any difference. I also tried the following code that I found on codeleaks.io. I added the following code in my login script:
session_start();
$_SESSION['start'] = time();
$_SESSION['expire'] = $_SESSION['start'] + (60);
And the following code on my landing page after logging in:
$currentTime = time();
if($currentTime > $_SESSION['expire']) {
session_unset();
session_destroy();
}
I set 60 seconds just to see if it works. And indeed, this works. Session will expire after 60 seconds. But when I want this session to last more than 24 hours then it doesn't work. So something else is destroying the session. I can't figure out what it is. I hope one of you guys can help me. Please note that I'm just an amateur.
To increase the login session timeout in PHP, you can use the session_set_cookie_params() function to set the lifetime of the session cookie. This function takes two parameters: the lifetime of the cookie in seconds, and the path on the server in which the cookie will be available. For example, to set the session timeout to 2 hours, you can use the following code:
$lifetime = 7200;
session_set_cookie_params($lifetime);
session_start();
This will set the session cookie to expire after 2 hours (7200 seconds) of inactivity.
Alternatively, you can also set the session timeout using ini_set() function
ini_set('session.gc_maxlifetime', 7200);
session_start();
Please note that you need to call session_start() after setting the parameters to take effect

PHP: pop show that app server time out

I have a PHP app written in codeIgniter. Getting some complaints from clients about the app timing out. Their session times out after two hours of inactivity and they can't seem to remember that.
Is there a way and if so, how, to show a pop up message when a users session has timed out?
Thank you in advance.
PHP cannot display a pop up by itself, but you could probably have a JavaScript query the session status and display a pop up when the session is expired, or even better, count the time since the session opened and let the user know in advance that his session is about to time out
If you want change the duration of the session, see this line in your config.php
$config['sess_expiration'] = 7200;
7200 is 120 minutes * 60 seconds. If you change it to 0, the session will not expire.
To add a warning, the very simplest method would probably to add a JavaScript similar to
setTimeout(function(){alert("Your session will expire in 5 minutes")},6900000); // 6900 seconds (115 minutes) * 1000 milliseconds
You could do it using:
Javascript function using timers (and show a popup after a period of time)
In PHP using a timer set in your $_SESSION and calculate the difference in timestamps (when the user is redirected to a login page, pass a message "Your session has timed out")
A hard-timeout/page redirect using a meta equiv tag to a session-timeout page.
You can even go as far as offering different timeout periods for different user groups...
An example using PHP, which logs them out, tells them and redirects once they log back in:
// get time now
$now = time();
// Set session period
$autologout = '7200';
if (isset($_SESSION["TimeOut"]))
{
if ($now > $_SESSION["TimeOut"])
{
// Unregister session and set message
session_unregister("authenticatedUser");
session_register("loginMessage");
$loginMessage = "Your session has timed out";
// Capture request URL and store in a cookie so that they
// are logged back into the page they were requesting
$requestURL = $_SERVER[REQUEST_URI];
setcookie("requestURL",$requestURL,"0",'/','',FALSE,TRUE);
// Redirect back to login page
header("Location: " . $loginScript);
exit;
} else {
$_SESSION['TimeOut'] = ($now + $autologout);
}
} else {
$_SESSION['TimeOut'] = ($now + $autologout);
}
This presumes that your system session timeouts are longer or set otherwise. It's not written for codeIgnitor either, but hopefully helpful to understand what can be done to soften the blow of session expiry.
Probarly your session maxlifetime is 2 hours.
You can edit that with this: (replace 8 with the max lifetime in hours).
ini_set(’session.gc_maxlifetime’, 8*60*60);

How to set lifetime of session

How to set session lifetime in PHP? I Want to set it to forever as long as the request is exist. The request is AJAX. My PHP code that handle AJAX request is:
// AJAX.php
<?php
session_start();
$_SESSION['counter'] = $_SESSION['counter'] + 1;
header('Content-type: application/json');
echo json_encode(array('tick' => $_SESSION['counter']));
?>
and the JavaScript:
$(document).ready(function() {
function check() {
getJSON('ajax.php');
}
function getJSON(url) {
return $.getJSON(
url,
function(data) {
$("#ticker").html(data.tick);
}
);
}
setInterval(function() {
check();
}, 10000); // Tick every 10 seconds
});
The session always resets after 300 seconds.
The sessions on PHP works with a Cookie type session, while on server-side the session information is constantly deleted.
For set the time life in php, you can use the function session_set_cookie_params, before the session_start:
session_set_cookie_params(3600,"/");
session_start();
For ex, 3600 seconds is one hour, for 2 hours 3600*2 = 7200.
But it is session cookie, the browser can expire it by itself, if you want to save large time sessions (like remember login), you need to save the data in the server and a standard cookie in the client side.
You can have a Table "Sessions":
session_id int
session_hash varchar(20)
session_data text
And validating a Cookie, you save the "session id" and the "hash" (for security) on client side, and you can save the session's data on the server side, ex:
On login:
setcookie('sessid', $sessionid, 604800); // One week or seven days
setcookie('sesshash', $sessionhash, 604800); // One week or seven days
// And save the session data:
saveSessionData($sessionid, $sessionhash, serialize($_SESSION)); // saveSessionData is your function
If the user return:
if (isset($_COOKIE['sessid'])) {
if (valide_session($_COOKIE['sessid'], $_COOKIE['sesshash'])) {
$_SESSION = unserialize(get_session_data($_COOKIE['sessid']));
} else {
// Dont validate the hash, possible session falsification
}
}
Obviously, save all session/cookies calls, before sending data.
Set following php parameters to same value in seconds:
session.cookie_lifetime
session.gc_maxlifetime
in php.ini, .htaccess or for example with
ini_set('session.cookie_lifetime', 86400);
ini_set('session.gc_maxlifetime', 86400);
for a day.
Links:
http://www.php.net/manual/en/session.configuration.php
http://www.php.net/manual/en/function.ini-set.php
Prior to PHP 7, the session_start() function did not directly accept any configuration options. Now you can do it this way
<?php
// This sends a persistent cookie that lasts a day.
session_start([
'cookie_lifetime' => 86400,
]);
?>
Reference: https://php.net/manual/en/function.session-start.php#example-5976
Sessions can be configured in your php.ini file or in your .htaccess file. Have a look at the PHP session documentation.
What you basically want to do is look for the line session.cookie_lifetime in php.ini and make it's value is 0 so that the session cookie is valid until the browser is closed. If you can't edit that file, you could add php_value session.cookie_lifetime 0 to your .htaccess file.
Since most sessions are stored in a COOKIE (as per the above comments and solutions) it is important to make sure the COOKIE is flagged as a SECURE one (front C#):
myHttpOnlyCookie.HttpOnly = true;
and/or vie php.ini (default TRUE since php 5.3):
session.cookie_httponly = True
I dont see this mentioned anywhere, but setting ini_set('session.gc_maxlifetime', $max_lifetime); in the PHP file itself is usually not going to have the desired affect if the php.ini file has a LOWER value and the server hosts multiple domains/vhosts. If you have User on X website, and the maxlifetime is set to 10 seconds (not a real value, this is just for example) in the PHP file and then have the maxlifetime set to 5 in php.ini something interesting/unexpected will happen if you have multiple domains/vhosts.
When a 2nd user visits a site that HASNT set ini_set('session.gc_maxlifetime', $max_lifetime); in it's PHP file and it defaults to whatever php.ini has, that will cause PHP's garbage collection to fire using 5 seconds rather than 10 seconds as maxlifetime, thus deleting the user's session which was supposed to last at least 10 seconds.
Therefore, this setting should almost NEVER go in the PHP file itself and should actually be in the vhost entry if your setup has this capability and falls into this type of scenario. The only exception to this is if your server only hosts 1 website/vhost who's PHP files will always override whatever php.ini has.
This happens because all sites use the same tmp dir to store session data. Another mitigation solution would be to set the session tmp dir per vhost. And yet another (not recommended) solution is to simply disable session.cookie_lifetime completely in php.ini by setting it to 0.
As long as the User does not delete their cookies or close their browser, the session should stay in existence.

PHP session_id() not accepting existing session id

I'm having trouble forcing sessions to restart in PHP. Here's the problem:
I can get my session id with session_id(), copy it, and add to the very top of my script:
session_id('the_session_id');
session_start();
And when I open a new browser, the session from the other browser is not carried over. What settings can I check?
Reason:
If you close the browser window and open it again, then at this moment a second session is started with a different ID, if the used web application has some session based authentication system the user has to login again. At the same time the user has to logout twice!
Solution:
This function will use a real cookie for the session ID and updates the expiration time with every script execution. The expiration is equal to the PHP directive "gc_maxlifetime" (default) or every custom value. So, put this function in your PHP file. We will need it.
<?php
// $expire = the time in seconds until a session have to expire
function start_session($expire = 0)
{
if ($expire == 0)
$expire = ini_get("session.gc_maxlifetime");
else
ini_set("session.gc_maxlifetime", $expire);
if (empty($_COOKIE['PHPSESSID']))
{
session_set_cookie_params($expire);
session_start();
}
else
{
session_start();
setcookie("PHPSESSID", session_id(), time() + $expire);
}
}
?>
Now, in the top of your page where you're issuing session_id('the_session_id'); and session_start();, remove those lines and start session with this code below:
To start a session with an expire time given by the php configuration
start_session();
To start a session that will expire in 1 hour:
start_session(3600);

PHP session lifetime problem

I'm using PHP5 here. I have made a login system that check's the username and password against the records in the database. I want to use sessions to store the logged value. For example, when I reach the zone where I "log in" the user succesfully:
if($errors = 0) {
$_SESSION['logged'] = "1";
}
The problem is that I want the $_SESSION['logged'] to stay active for let's say 5 minutes so when I do a if($_SESSION['logged'] == "1") after this time to return false. Also, I would like to delete this session after the user closes the browser. Basically, I want a session configuration so that the user can safely leave his desk and when him or somebody presses refresh after 10 minutes or enters again after the browser has been closed, the session to be already removed, and the access to be restricted.
Can anybody help? Thanks.
Use session_set_cookie_params() to change the lifetime of the session cookie. Note that by default, it is set to 0 which means that the cookie is set until the user exits the browser. You can do this in the following way:
/* Set to 0 if you want the session
cookie to be set until the user closes
the browser. Use time() + seconds
otherwise. */
session_set_cookie_params(0);
session_start();
Then check for the last activity time, updated each time someone visits a page.
if(($_SESSION['lastActivity'] + 300) < time()) {
// timeout, destroy the session.
session_destroy();
unset($_SESSION);
die('Timeout!');
} else {
$_SESSION['lastActivity'] = time();
}
Instead of setting it to one, why don't you set $_SESSION['logged_time'] = time(); and then check the time against time() in your application?
If you'd like to actually expire the entire session, the exact specifics can change depending on your session handler, but for the default session handler (and any other well behaved session handler) you'll want to check out http://us3.php.net/manual/en/session.configuration.php
You can change the configuration setting session.cookie_lifetime, e.g. in php.ini or a .htaccess file:
session.cookie_lifetime specifies the
lifetime of the cookie in seconds
which is sent to the browser. The
value 0 means "until the browser is
closed." Defaults to 0.
This means (I think) that you can't have both expiry based on a timeout and expiry when the browser is closed. So maybe the best bet is to keep the default and set your own timer in $_SESSION as others have suggested, thus rendering this answer pointless.
Sessions stay alive aslong as the user stays on your site. You will have to use cookies to set a specific timeout.

Categories