I want to build a login system in PHP. There are 5 files:
db.php
contains database utilities.user.php
for login and logout functions.login.php
is login page.index.php
is the main page.logout.php
is a page that logs users out and redirects tologin.php
.
The login part seems to work as expected (by checking the database, omitted here), but the redirection from login.php
to index.php
doesn't seem to work. The same login page appears again.
But when I remove this part in index.php
:
// Must be logged in first
if (!isset($_SESSION['username'])) {
gotoPage('login.php');
}
it redirects successfully, and then the logout fails.
Also, if a user logs out and clicks the undo button in the browser, it takes him to the main page (index.php
) which he is not supposed to see after logging out.
I don't know what exactly is preventing the redirection and the logout. Any help (or advice) is appreciated.
Note: I've looked at similar questions on SO, none of the answers provided solved the issue.
db.php
content:
<?php
function getDBInstance() : PDO
{
static $dbInstance;
if (!$dbInstance) {
return new PDO(
'mysql:host=localhost;dbname=DummyUserAccounts;charset=UTF8',
'dummyuser',
'...',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
}
return $dbInstance;
}
function register_user(string $firstname, string $lastname, string $username, string $password): bool
{
// PROC_USER_ADD inserts one user into the User table.
$query = 'CALL PROC_USER_ADD(:firstname, :lastname, :username, :password)';
$statement = getDBInstance()->prepare($query);
$statement->bindValue(':firstname', $firstname, PDO::PARAM_STR);
$statement->bindValue(':lastname', $lastname, PDO::PARAM_STR);
$statement->bindValue(':username', $username, PDO::PARAM_STR);
$statement->bindValue(':password', password_hash($password, PASSWORD_BCRYPT), PDO::PARAM_STR);
return $statement->execute();
}
?>
user.php
content:
<?php
require 'db.php';
function sanitize($field)
{
$field = trim($field);
$field = stripslashes($field);
$field = htmlspecialchars($field);
return $field;
}
function gotoPage(string $page) : void
{
header('Location: ' . $page);
exit;
}
function loginUser(string $username, string $password) : bool
{
// Search for the user in the database
$queryString = 'SELECT username, password FROM user WHERE username = :username';
$statement = getDBInstance()->prepare($queryString);
$statement->bindValue(':username', $username, PDO::PARAM_STR);
$statement->execute();
$user = $statement->fetch(PDO::FETCH_ASSOC);
// Successful login?
if ($user && password_verify($password, $user['password'])) {
// Create a new Session ID
session_start();
// Write session data
$_SESSION['username'] = $username;
return true;
}
return false;
}
function logoutCurrentUser() : void
{
if (isset($_SESSION['username'])) {
unset($_SESSION['username']);
session_destroy();
gotoPage('login.php');
}
}
?>
login.php
content:
<?php
require 'user.php';
// Can't login twice.
if (isset($_SESSION['username'])) {
gotoPage('index.php');
}
$errorMessage = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Check for empty fields
if (empty($_POST['username']) || empty($_POST['password'])) {
$errorMessage = "Both Username and Password are required!";
} else {
// Sanitize fields
$username = sanitize($_POST['username']);
$password = sanitize($_POST['password']);
// Login user
if (!loginUser($username, $password)) {
$errorMessage = "Invalid username and/or password.";
} else {
gotoPage('index.php');
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form action="login.php" method="post">
<div>
<label>Username</label>
<input type="text" name="username">
</div>
<div>
<label>Password</label>
<input type="password" name="password">
</div>
<div>
<button type="submit">Login</button>
</div>
<div>
<span style="color:red"><?php echo $errorMessage ?></span>
</div>
</form>
</body>
</html>
index.php
content:
<?php
require 'user.php';
// Must be logged in first
if (!isset($_SESSION['username'])) {
gotoPage('login.php');
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Main Page</title>
</head>
<body>
<nav>
<a href="logout.php">Logout</a>
</nav>
<!--Main page goes here-->
</body>
</html>
logout.php
content:
<?php
require 'user.php';
logoutCurrentUser();
gotoPage('login.php');
?>
CodePudding user response:
You will need session_start()
on every page that you want to access $_SESSION
variables. login.php
does not have session_start()
, so isset($_SESSION)
will always return false
.