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.

1 Answer 1

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>.

8
  • thanks a lot @clive, wrapping my head to digest, thanks again!
    – arpitr
    Feb 16, 2017 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, 2017 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, 2017 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. Feb 17, 2017 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, 2017 at 11:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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