9

Previously i was creating additional cookie "rememberme" with unique hash, that was stored in the database, mapped to the user id.

If user had such cookie - website tried to find it's value in database, and if it was found session was setting up.

Later, developing new project i thought that it is maybe not very secure to generate this unique hash by myself, and keeping two cookies (native "PHPSESSID" + my "rememberme") for one operation (user identification) is overkill.

Maybe there is a way to setup not global session lifetime, but to setup it individually for different user sessions... or maybe it is better to keep user sessions in the database, mapped to the userid?

UPDATE 1 I thought if it is so hard to make "remember me" button, we can go another way - to make "Not my computer button". Idea is to set default cookie_lifetime for a week in php.ini (for example), and if user checkes this checkbox - we will set cookie_lifetime into zero using session_set_cookie_params function.

So, 1st question is - will session_set_cookie_params affect other users cookies (in documentation it is said, that session_set_cookie_params options will have effect until php process will be executing)

2d question is that if session_set_cookie_params is not affecting global settings, will session regeneration affect users, that don't want to keep a long-life cookie?

UPDATE 2: [Question 1 answer]

Just tested session_set_cookie_params function. I wrote a script, that sets session cookie lifetime into zero using session_set_cookie_params and then executing for 30 seconds:

if ($_GET['test']) {
  session_set_cookie_params (0);
  while (true) {
    sleep(1);
  }
}
session_start();

So, in first browser i just started this script with ?test=1 parameter, just after that (while this script was executing) i started this script without parameters in the second browser. The answer is no - second browser's cookie was not affected. It had lifetime, that was specified in php.ini

UPDATE 3: [Question 2 answer] Then, i've tried to check if regeneration affects session cookie lifetime, that was set by session_set_cookie_params.

Yes, it affects. If i set session cookie with customized lifetime, that was set by session_set_cookie_params, and then call session_regenerate_id(), cookie will have lifetime, set in php.ini

But, if we set session_set_cookie_params (0) before calling session_regenerate_id(), our cookie will have correct lifetime.

So, that's it! That was easy! 8)

Thank you, ladies and gentlemen!

avasin
  • 9,186
  • 18
  • 80
  • 127
  • I don't get it. Session lifetime doesn't affect the fact that the user will get a new PHPSESSID once browser is restared. Please elaborate your security concerns. – Teson Oct 19 '12 at 09:42
  • I would like to keep one cookie for user identification. I am not sure that my custom cookie "rememberme" is secure, more over, i don't want to think about it - two cookies for one operation is too redundant. – avasin Oct 19 '12 at 09:48
  • The one straightforward way is to use one or two cookies with value `SHA1($userid.$salt)` and public `username`. – Stan Oct 19 '12 at 11:06
  • Just to clarify my previuos comment, I don't think that these two cookies are for the same purposes, because session state and _rememberme_ between sessions are different entities. So it's a good approach to have them separated, but it's not necessary to store _rememberme_ in DB. Moreover it's inefficient to make sessions leave "forever" just to keep _remeberme_ flag. – Stan Oct 19 '12 at 12:04
  • Today i got idea to change task a little bit. We can make big ttl for sessions by default, and add checkbox "Not mine computer". If it will be checked - session cookie lifetime for current user will be set to zero with session_set_cookie_params function. So, the question is: "Does session_set_cookie_params has global effect or just affects current script execution?" And second problem can be.. hm.. session regeneration (as i understand php regenerates it somehow) – avasin Oct 21 '12 at 00:33
  • Just made little check: i've set ession.cookie_lifetime = 100500 in php.ini and wrote a script, that used to set session_set_cookie_params(0) and executing then for 30 seconds. While this script was executing, i tried to setup session in another browser.. and cookie lifetime was not zero. – avasin Oct 21 '12 at 00:46

2 Answers2

2

If you want to do this only using sessions you can do the following if the user wants to be remembered:

if((isset($_POST['remember_me']) && $_POST['remember_me']) || ($_COOKIE['remember_me']) && $_COOKIE['remember_me'])) {

  // store these cookies in an other directory to make sure they don't
  // get deleted by the garbage collector when starting a "non-remeber-me"-session
  $remember_me_dir = ini_get('session.save_path') . DS . "remember_me_sessions";

  // create the directory if it doesn't exist
  if (!is_dir($remember_me_dir)) {
    mkdir($remember_me_dir);
  }

  // set the php.ini-directive (temporarily)
  ini_set('session.save_path', $remember_me_dir);

  // define lifetime of the cookie on client side
  $expire_cookie = 60 * 60 * 24 * 30; // in seconds
  session_set_cookie_params($expire_cookie);

  // lifetime of the cookie on server side
  // session file gets deleted after this timespan
  // add a few seconds to make sure the browser deletes
  // the cookie first.
  $garbage_in = $expire_cookie + 600; // in seconds

  // set the php-ini directive for the garbage collector of the session files.
  ini_set('session.gc_maxlifetime', $garbage_in);    
  // send an additional cookie to keep track of the users 
  // which checked the 'remember_me' checkbox
  setcookie('remember_me', 1, time() + $expire_cookie);
}

// now we are ready to start the session
// For all the users which didn't choose to check the 'remember_me' box
// the default settings in php.ini are used.
session_start();

Here you can read more about the session related php.ini-directives

MarcDefiant
  • 6,649
  • 6
  • 29
  • 49
  • Hmm.. maybe there can be a way to setup all session cookies for a week for example with checkbox "Not mine computer". If this checkbox will be checked, before setting session cookie we will set session cookie lifetime with session_set_cookie_params to zero? – avasin Oct 21 '12 at 00:26
  • So, the question is: "Does session_set_cookie_params has global effect or just affects current script execution?" And second problem can be.. hm.. session regeneration (as i understand php regenerates it somehow) – avasin Oct 21 '12 at 00:29
2

As it was so hard to make "remember me" checkbox functionality, i came to another way, using only one cookie.

PREPARATION

1) I've prepared a form with three inputs:

  • "login" input [type=text]: user's login
  • "password" input [type=password]: user's password
  • "not my computer" input [type=checkbox]: that will tell us to use session cookie with lifetime = 0 (cookie must be deleted when browser will be closed)

2) I've set session.cookie_lifetime = 100500 to keep long-life cookies by default.

COOKIE SETUP

So, after user submits the form, we check - if he has selected to use short sessions - we call session_set_cookie_params(0) before setting session cookie to him (before actually using session_start()).

COOKIE REGENERATION

Then, when we need to regenerate session cookie, we can also do this easily with session_regenerate_id() function. But we need to remember, that this function will re-set session cookie lifetime from php.ini by default. So, we need also to call session_set_cookie_params() before regenerating a cookie. BTW, You can store custom session cookie lifetime in $_SESSION. It will look like this:

// Form handling, session setup
if ($_POST['not-my-computer']) {
   session_set_cookie_params(0);
   session_start();
   $_SESSION['expires'] = 0;
}

// Session regeneration 
if (isset($_SESSION['expires'])) {
    session_set_cookie_params(0);
    session_regenerate_id();
}

Details for this answer (and more deep explanations) you can find in the question text (while i was testing, i added answers/tests results there)

avasin
  • 9,186
  • 18
  • 80
  • 127