James Jeffery
James Jeffery

Reputation: 55

No Session after logging in

I have a strange issue. I've create a login page in PHP that works fine. I've decided to destroy any session when a user hits the login page. But, by doing this the user is never logged in. I can't see the issue.

Login page

<?php
session_start();

// Destroy any active session
session_destroy();

// Regenerate Session ID
session_regenerate_id(true);

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    $username = $_POST['username'];
    $password = md5($_POST['password']);

    if(strlen($username) > 12) {
        header('Location: index.php');
    }

    try {
        $dbh = new PDO('mysql:dbname=addcovers;host=127.0.0.1', 'root', '');
        $sth = $dbh->prepare('SELECT display_name FROM users WHERE username = :username && password = :password');
        $sth->bindParam(':username', $username, PDO::PARAM_STR, 12);
        $sth->bindParam(':password', $password, PDO::PARAM_STR, 32);
        $sth->execute();
        $result = $sth->fetch(PDO::FETCH_OBJ);

        if($result) {
            $_SESSION['logged_in'] = true;
            $_SESSION['user'] = $result->display_name;
            header('Location: index.php');
        }
    } catch (PDOException $e) {
        // DEBUG: echo 'Connection failed: ' . $e->getMessage();
    }

}
?>
<!DOCTYLE html>
<html>
<head>
    <title></title>

    <link rel="stylesheet" href="css/reset.css" type="text/css" media="all">
    <link rel="stylesheet" href="css/base.css" type="text/css" media="all">
</head>

<body id="admin-login">
    <form action="login.php" method="POST">
        <fieldset>
            <div><label for="username">Username</label><input type="text" name="username" maxlength="12"></div>
            <div><label for="password">Password</label><input type="password" name="password"></div>
            <button type="submit">Admin Login</button>
        </fieldset>
    </form>
</body>

Admin Page

<?php
session_start();

if(!isset($_SESSION['logged_in'])) header('Location: login.php');

echo 'Welcome ' . $_SESSION['user'];

?>

If I remove the session_destroy from the login page it works fine. Currently though the user keeps hitting the login page even if the credentials are correct.

Upvotes: 0

Views: 568

Answers (3)

Abhi Beckert
Abhi Beckert

Reputation: 33369

You cannot do a header-location redirect immediately after changing the session id. You are creating a new session id, but the new one isn't being sent back to the browser because you do a redirect. So the browser continues to use the old session id (which is empty, because you destroyed it).

Note PHP's docmuentation:

Session ID is not passed with Location header even if session.use_trans_sid is enabled. It must by passed manually using SID constant.

As to how to fix it, I'm not sure. A quick search doesn't show much. Perhaps you need to read the SID constant and manually send the correct headers for the new session id back to the browser, as part of your redirect.

Or you could show one of those "you have been logged in" messages for a second, then use javascript or a <meta> tag to redirect to index.php.

Also note This line of code:

header('Location: index.php');

Will only send a header response for the current request which is to login.php. It will still continue executing your script. In general you should always exit after sending that header:

header('Location: index.php');
exit;

I don't think that will cause your bug, but you should fix it.

Upvotes: 1

Jon
Jon

Reputation: 437604

There is no benefit to calling session_destroy just before logging the user in (or indeed when the user simply visits the login page, as your script currently does) -- and even if you really want to do that, this is not the correct way to do it.

The documentation for session_destroy says that after calling it,

To use the session variables again, session_start() has to be called.

You don't do this, so the session variables you set later do not "stick" and the admin page redirects back to login.

If you do want to completely destroy the user session, then:

  1. Follow the example in the docs: destroy the session, regenerate the id, unset $_SESSION and also unset the session cookie.
  2. Do this only if the user has passed the username/password check, not unconditionally.
  3. Call session_start again before setting any session variables for the new session.

Upvotes: 0

redShadow
redShadow

Reputation: 6777

What if you comment out this line in index.php ?

if(!isset($_SESSION['logged_in'])) header('Location: login.php');

(That is: does the index.php see stuff in the session? Try also by printing a var_export($_SESSION);)

I remember that PHP sessions were giving some apparently random issues, depending on $_SESSION not being global, for what I remember; but your code seems to be in the global scope.. am I right?

Upvotes: 0

Related Questions