5

The following code, let's login any user programmatically.

global $user;
$user = user_load(<any_uid>);

My question is how does the above code triggers to set new user cookies on browser, at this point we are not even regenerating session.

7

The following code, let's login any user programmatically.

Not exactly; it sets the current global user object to an instance of a user, but it doesn't log the account in or touch the session. Many things that happen in that request that rely on the global user object will behave the same as if the account was logged in, but it won't be, and they won't have a session tied to the account (not yet anyway).

Cookies are added at the end of the request, in drupal_session_commit:

if (!drupal_session_started()) {
  drupal_session_start();
  if ($is_https && variable_get('https', FALSE)) {
    $insecure_session_name = substr(session_name(), 1);
    $params = session_get_cookie_params();
    $expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0;
    setcookie($insecure_session_name, $_COOKIE[$insecure_session_name], $expire, $params['path'], $params['domain'], FALSE, $params['httponly']);
  }
}

As a by-product of the way Drupal initialises sessions (lazily in an exit hook), if the call to $user = user_load(<any_uid>); happens before the first session has been initialised, the session will be initialised for that user and they will appear "logged in" for their next request, even if the user_load line doesn't execute.

But, hook_user_login won't have been invoked, the last login column in the user table won't be updated, and so on. It's not a full-on "login", just initialising the session for a particular user.

Incidentally, if you call $user = user_load(<any_uid>); when a session already exists for another user, the session for the next request will still be for that other user. It won't be overridden with a session for <any_uid>.

  • thanks a lot @clive, wrapping my head to digest, thanks again! – arpitr Feb 16 '17 at 21:05
  • 1
    No worries, it was interesting to work this out; feel free to ask follow-up questions, it's still fresh :) – Clive Feb 16 '17 at 21:06
  • ah! I see my next question was what if I do drupal_goto() right after $user = $user_load(<any_uid>);, but realised drupal_goto() calls drupal_exit(); – arpitr Feb 16 '17 at 21:20
  • 1
    I think the reason why session id get replaced in database when you do die() right after user_load(<any_uid>) is because of drupal uses _drupal_session_write() function as session write handler in session_set_save_handler() function. This _drupal_session_write() function get executed right before script exits and in this function drupal update the existing session with new user id. See php.net/manual/en/function.session-set-save-handler.php for more detail. – MutantMahesh Feb 17 '17 at 8:23
  • 1
    The session gets written and closed in a registered shutdown function, which runs even when die is used . Many layers at work here – Clive Feb 17 '17 at 11:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.