Progromatic World Forum
how to create a login form using a username and password - Printable Version

+- Progromatic World Forum (https://progromatic.online/forum)
+-- Forum: Web Category (https://progromatic.online/forum/forumdisplay.php?fid=9)
+--- Forum: PHP Codes & Scripts (https://progromatic.online/forum/forumdisplay.php?fid=10)
+--- Thread: how to create a login form using a username and password (/showthread.php?tid=14)



how to create a login form using a username and password - Progromatic Admin - 08-23-2024

PHP Login
Summary: in this tutorial, you’ll learn how to create a login form using a username and password.

Prerequisites
To start this tutorial, you need to complete the previous tutorial that creates a registration form.

Introduction to the PHP login form
In the previous tutorial, you learned how to create a form that allows users to register for accounts. Once the users register successfully, you redirect them to the login page so that they can use their usernames and passwords to log in.

The login page will contain a form that consists of the username and password inputs and a login button as follows:

PHP Login
To log in, users need to enter their username and password and click the login button.

If the username and password match, you can redirect them to a password-protected page. Otherwise, you redirect the users back to the login page with an error message:


Note that it’s more secure to issue a generic message (invalid username or password) when either username or password doesn’t match.

Create the login form
First, create the login.php page in the public folder.

Second, define a login form with the username and password inputs and a login button:

PHP Code:
<!DOCTYPE html>
<
html lang="en">
<
head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://www.phptutorial.net/app/css/style.css">
    <title>Login</title>
</
head>
<
body>
<
main>
    <form action="login.php" method="post">
        <h1>Login</h1>
        <div>
            <label for="username">Username:</label>
            <input type="text" name="username" id="username">
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" name="password" id="password">
        </div>
        <section>
            <button type="submit">Login</button>
            <a href="register.php">Register</a>
        </section>
    </form>
</
main>
</
body>
</
html

Like the register.php page, you can reuse the header.php and footer.php files from the src/inc folder and use the view() function to load them to the login.php page as follows:

PHP Code:
<?php

require __DIR__ '/../src/bootstrap.php';
?>

<?php view('header', ['title' => 'Login']) ?>
<main>
    <form action="login.php" method="post">
        <h1>Login</h1>
        <div>
            <label for="username">Username:</label>
            <input type="text" name="username" id="username">
        </div>

        <div>
            <label for="password">Password:</label>
            <input type="password" name="password" id="password">
        </div>

        <section>
            <button type="submit">Login</button>
            <a href="register.php">Register</a>
        </section>
    </form>
</main>
<?php view('footer'?>

The login form submits to login.php. Therefore, you can check if the HTTP request method is POST before processing the form.

To process the form, you create the login.php in the src folder.

PHP Code:
<?php

$inputs 
= [];
$errors = [];

if (
is_post_request()) {

    [$inputs$errors] = filter($_POST, [
        'username' => 'string | required',
        'password' => 'string | required'
    ]);

    if ($errors) {
        redirect_with('login.php', ['errors' => $errors'inputs' => $inputs]);
    }

    // if login fails
    if (!login($inputs['username'], $inputs['password'])) {

        $errors['login'] = 'Invalid username or password';

        redirect_with('login.php', [
            'errors' => $errors,
            'inputs' => $inputs
        
]);
    }
    // login successfully
    redirect_to('index.php');

} else if (
is_get_request()) {
    [$errors$inputs] = session_flash('errors''inputs');


How it works.

First, define two variables to store the sanitized data and error messages:

PHP Code:
$inputs = [];
$errors = []; 

Second, check if the HTTP request method is POST using the is_post_request() function:

PHP Code:
if (is_post_request()) {
    // ...


Third, sanitize and validate user inputs using the filter() function:

PHP Code:
[$inputs$errors] = filter($_POST, [
    'username' => 'string | required',
    'password' => 'string | required'
]); 

Fourth, if either username or password is not provided, redirect users to the login.php page using the post-redirect-get (PRG) technique and set the $errors and $inputs in the session using the redirect_with() function.

PHP Code:
if ($errors) {
    redirect_with('login.php', [
        'errors' => $errors,
        'inputs' => $inputs
    
]);


Fifth, call the login() function to verify the username and password.

If either username or password doesn’t match, set an error message with the key login and redirect users back to the login.php page:

PHP Code:
<?php

if (!login($inputs['username'], $inputs['password'])) {

    $errors['login'] = 'Invalid username or password';

    redirect_with('login.php', [
        'errors' => $errors,
        'inputs' => $inputs
    
]);


Seventh, if both username and password match, redirect users to the index.php page:

PHP Code:
redirect_to('index.php'); 

The index.php is the password-protected page. It means that only logged-in users can access it—more on this in the next section.

Finally, get the $inputs and $errors from the session if the HTTP request method is GET.

PHP Code:
[$errors$inputs] = session_flash('errors''inputs'); 

Show the entered data & error message on the login.php page
The public/login.php needs to change to the following to show the user inputs as well as error messages:

PHP Code:
<?php

require __DIR__ '/../src/bootstrap.php';
require 
__DIR__ '/../src/login.php';
?>

<?php view('header', ['title' => 'Login']) ?>

<?php if (isset($errors['login'])) : ?>
    <div class="alert alert-error">
        <?= $errors['login'?>
    </div>
<?php endif ?>

    <form action="login.php" method="post">
        <h1>Login</h1>
        <div>
            <label for="username">Username:</label>
            <input type="text" name="username" id="username" value="<?= $inputs['username'] ?? '' ?>">
            <small><?= $errors['username'] ?? '' ?></small>
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" name="password" id="password">
            <small><?= $errors['password'] ?? '' ?></small>
        </div>
        <section>
            <button type="submit">Login</button>
            <a href="register.php">Register</a>
        </section>
    </form>

<?php view('footer'?>

Since the login() function doesn’t exist, we need to define it.

Define the login() function
The login() function accepts username and password and returns true if they are valid. The logic of the login() function is as follows:

First, find the username in the users table. If the user exists, go to step 2.
Second, verify if the password matches.
Third, if the username doesn’t exist or the password doesn’t match, issue an error message.
To find a user from the users table by username, you can define a function find_user_by_username() in the src/auth.php file:

PHP Code:
function find_user_by_username(string $username)
{
    $sql 'SELECT username, password
            FROM users
            WHERE username=:username'
;

    $statement db()->prepare($sql);
    $statement->bindValue(':username'$usernamePDO::PARAM_STR);
    $statement->execute();

    return $statement->fetch(PDO::FETCH_ASSOC);


If a username exists in the users table, the find_user_by_username() function returns an associative array with two elements whose keys are username and password. Otherwise, it returns false.

Since you store the password hash in the database, you need to use the built-in password_verify() function to match the plain password with a hash.

The password_verify() function returns true if a plain text password matches a hash, or false otherwise.

If both username and password match, you can log the user in. To do that, you need to set a value in the $_SESSION for example:

PHP Code:
$_SESSION['username'] = $username

In subsequent requests, you can check the $_SESSION variable to see if the user with a username is currently logged in. For example:

PHP Code:
// check if the username has been logged in
if(isset($_SESSION['username'])) {
    // already logged in
    // ...



Here’s the complete login() function:

PHP Code:
function login(string $usernamestring $password): bool
{
    $user find_user_by_username($username);

    // if user found, check the password
    if ($user && password_verify($password$user['password'])) {

        // prevent session fixation attack
        session_regenerate_id();

        // set username in the session
        $_SESSION['username'] = $user['username'];
        $_SESSION['user_id']  $user['id'];


        return true;
    }

    return false;



Note that you should call the session_regenerate_id() function to regenerate a new session id if when users start logging in. It helps prevent the session fixation attack.

The following defines the is_user_logged_in() function in the src/auth.php file, which returns true if a user is currently logged in:

PHP Code:
function is_user_logged_in(): bool
{
    return isset($_SESSION['username']);



If users have not logged in, you can redirect them to the login.php page. The following defines the require_login() function that redirects to the login.php page if the current user is not logged in:

PHP Code:
function require_login(): void
{
    if (!is_user_logged_in()) {
        redirect_to('login.php');
    }



And you can call the require_login() function at the beginning of any page that requires login.

For example, you can call it in the public/index.php page like this:

PHP Code:
<?php

require __DIR__ '/../src/bootstrap.php';
require_login();
?>


Log a user out
To log a user out, you need to remove the value you set when logged in and redirect to the login.php page.

In the login() function, you add the username to the $_SESSION variable. Therefore, you need to remove it to log the user out.

The following defines the logout() function in the auth.php that logs a user out by removing the username and user_id from the $_SESSION variable:

PHP Code:
function logout(): void
{
    if (is_user_logged_in()) {
        unset($_SESSION['username'], $_SESSION['user_id']);
        session_destroy();
        redirect_to('login.php');
    }



The following defines the current_user() function that returns the username of the currently logged in user:

PHP Code:
function current_user()
{
    if (is_user_logged_in()) {
        return $_SESSION['username'];
    }
    return null;



Create the logout link
When users log in successfully, they are redirected to the index.php.

On the index.php, you can show a welcome message as well as a logout link like this:

PHP Code:
<?php

require __DIR__ '/../src/bootstrap.php';
require_login();
?>

<?php view('header', ['title' => 'Dashboard']) ?>
<p>Welcome <?= current_user() ?> <a href="logout.php">Logout</a></p>
<?php view('footer'?>


When users click the logout link, you need to call the logout() function to log the users out.

To do that, you need to create the logout.php in the public folder.

In the logout.php, you need to call the logout() function as follows:

PHP Code:
<?php

require __DIR__ '/../src/bootstrap.php';
logout(); 


Redirect if users already logged in
If users already logged in and navigate to the login.php or register.php page, you need to redirect them to the index.php.

To do it, you can add the following code to the beginning of the login.php and register.php file in the src folder:


PHP Code:
<?php

if (is_user_logged_in()) {
    redirect_to('index.php');



The following shows the login.php in the src folder:

PHP Code:
<?php

if (is_user_logged_in()) {
    redirect_to('index.php');
}

$inputs = [];
$errors = [];

if (
is_post_request()) {

    // sanitize & validate user inputs
    [$inputs$errors] = filter($_POST, [
        'username' => 'string | required',
        'password' => 'string | required'
    ]);

    // if validation error
    if ($errors) {
        redirect_with('login.php', [
            'errors' => $errors,
            'inputs' => $inputs
        
]);
    }

    // if login fails
    if (!login($inputs['username'], $inputs['password'])) {

        $errors['login'] = 'Invalid username or password';

        redirect_with('login.php', [
            'errors' => $errors,
            'inputs' => $inputs
        
]);
    }

    // login successfully
    redirect_to('index.php');

} else if (
is_get_request()) {
    [$errors$inputs] = session_flash('errors''inputs');



Summary
Use the password_verify() function to verify the password.
Call the session_regenerate_id() function to prevent the session fixation attack.
Add one or more values (username and user idl) to the $_SESSION variable to mark if a user has been logged in.


RE: how to create a login form using a username and password - xtestify - 01-30-2025

Всел133.2CHAPReprматеOttoAnytWatcПятистудцифрSydnNara`АлеАксюWalkNomaЛактЛемеАйваФролMaevСыро
PeteJeweповеWillПопоКолеТюлихронимевБабиHansКозиBritDaviSlimМедвEdaiвойнАфанElleфакувузоBril
товаПоснврачмужчЩитоВереСодеУрюпMODOгазоELEGElegMeshСодеAltaFrieОтечШишкHenrWestRiesRomaАдел
ИванAshfSelaKoffмолнSelaFallMichPaliFallСолоСан-sizeПавлАксеFRANMasyвлюбMichXVIIShibМалеМарт
ZoneКороMeanZoneZoneZoneZoneZoneСтал3095ZoneZoneсереZone9003СтояZoneZoneZoneZoneMileZoneZone
БредкабивладhandLeclSamsStieПроиМакГСолоМинчМихаЕпифFiesКитаXVIIIntrStanБереWaruрасслапаLand
ValiчитакрасAngeязыкLiPoWindAutoФедоиголкрасBoscBoscCastAdvaЛитРЛитРвероотдеWireMystDarkХрус
ЛитРЛитРИллюШевчПравРозеMicrAcadBuzzпункСокоAsiaBariдебюЮвентраннебе(ВедTangтехнСодеXVIISony
БулгЛобаНефеВахрJameстерКлушНоваобраразнDiviCuatЛайлPaul84x1КониСветLandHomeНефеШароhandhand
handMathANSIКузнСиняГрециздаАЯЛиPublавтопансотпрвозрtuchkasСерпEdwa