Reputation: 55
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
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
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:
$_SESSION
and also unset the session cookie.session_start
again before setting any session variables for the new session.Upvotes: 0
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