Blog about Web Programming and Electronics
💬 👤
back Back to blog
WEB (HTML, CSS, PHP)

How to Make a Login and Registration: Complete Guide with PHP

Login and user registration are the foundation of every web application that requires user accounts. Whether you are building an online store, a blog, or a web service, you must provide a secure registration and login process. In this article, we will cover the entire process — from the form to secure password storage and session management.

User Registration

Registration is the process where a user creates a new account. The core components of registration are:

  1. HTML form: User enters a username, email, and password
  2. Server-side validation: Server checks whether the data is valid and whether the user already exists
  3. Password hashing: The password is never stored in plain text — it is always hashed
  4. Database storage: User data (without the password) and the password hash are stored in the database

HTML Registration Form

Let's start with a simple registration form. We will use the POST method, as it is more secure for sending sensitive data:

<!-- register.html -->

<form action="register.php" method="POST">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" required>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>

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

    <button type="submit">Register</button>
</form>

PHP Registration Processing

When the user submits the form, the data is received by register.php. Three key things happen here: validation, checking for existing users, and password hashing.

<?php
// register.php

// Check if the form was submitted
if ($_SERVER["REQUEST_METHOD"] === "POST") {

    // Retrieve and sanitize input data
    $username = htmlspecialchars($_POST["username"]);
    $email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
    $password = $_POST["password"];

    // Validation
    if (!$username || !$email || strlen($password) < 8) {
        die("Please enter valid data. Password must be at least 8 characters.");
    }

    // Hash the password (bcrypt)
    $password_hash = password_hash($password, PASSWORD_DEFAULT);

    // Prepare SQL query (PDO with prepared statements)
    $stmt = $pdo->prepare("
        INSERT INTO users (username, email, password_hash)
        VALUES (:username, :email, :password_hash)
    ");

    // Execute with bound parameters (prevents SQL injection)
    $stmt->execute([
        ":username" => $username,
        ":email" => $email,
        ":password_hash" => $password_hash
    ]);

    echo "Registration successful! You can now log in.";
}
?>

Here are two key security functions:

Function Purpose When to use
password_hash() Creates a secure password hash (bcrypt) During new user registration
htmlspecialchars() Prevents XSS attacks (Cross-Site Scripting) Whenever outputting user input
filter_var() Validates email address format During email validation
PDO prepared statements Prevents SQL injection attacks For every database query with user data

User Login

Login is the process where a user accesses their existing account. The server checks whether the entered password matches the stored hash.

<!-- login.html -->

<form action="login.php" method="POST">
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>

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

    <button type="submit">Log in</button>
</form>

PHP Login Processing

<?php
// login.php

session_start();

if ($_SERVER["REQUEST_METHOD"] === "POST") {

    $email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
    $password = $_POST["password"];

    if (!$email || !$password) {
        die("Please enter valid data.");
    }

    // Find user by email
    $stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
    $stmt->execute([":email" => $email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    // Verify password
    if ($user && password_verify($password, $user["password_hash"])) {

        // Password is correct — create session
        $_SESSION["user_id"] = $user["id"];
        $_SESSION["username"] = $user["username"];

        echo "Welcome, " . htmlspecialchars($user["username"]) . "!";
        header("Location: dashboard.php");
        exit;

    } else {
        // Incorrect password or user does not exist
        echo "Incorrect email or password.";
    }
}
?>

Important: the error message should always be the same, regardless of whether the user does not exist or the password is incorrect. This prevents an attacker from determining whether an email is registered.

Session Management

Once the user is logged in, the server needs to remember who they are. This is achieved with sessions. A session starts with session_start() at the top of every protected page:

<?php
// dashboard.php — protected page

session_start();

// Check if user is logged in
if (!isset($_SESSION["user_id"])) {
    header("Location: login.html");
    exit;
}

echo "Welcome to the dashboard, "
    . htmlspecialchars($_SESSION["username"]) . "!";
?>

Logging out the user:

<?php
// logout.php

session_start();
session_unset(); // Clear all session variables
session_destroy(); // Destroy the session

header("Location: login.html");
exit;
?>

SQL Users Table

Here is an example SQL table for storing users:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(255) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Security Recommendations

  1. Never store passwords in plain text: Always use password_hash() with the bcrypt algorithm
  2. Use PDO with prepared statements: This is the only safe way to interact with a database
  3. Validate on the server side: HTML validation (required, type="email") is not enough — always validate in PHP too
  4. Use HTTPS: Without HTTPS, all data including passwords is transmitted in plain text
  5. Limit login attempts: Prevent brute-force attacks by limiting attempts (e.g., 5 attempts in 10 minutes)
  6. Never output user data without htmlspecialchars(): Prevent XSS attacks
  7. Require strong passwords: Demand a minimum of 8 characters, combining letters, numbers, and special characters
  8. Consider two-factor authentication (2FA): An additional layer of security for sensitive applications

Common Mistakes

Mistake Why it's dangerous Correct solution
Storing passwords in plain text If the database is breached, all passwords are compromised password_hash() with bcrypt
Using md5() or sha1() for passwords These algorithms are not secure for passwords password_hash() (uses bcrypt)
SQL queries with string concatenation Vulnerable to SQL injection PDO prepared statements with bound parameters
Outputting user input without sanitization Vulnerable to XSS attacks htmlspecialchars()
Different errors for "user not found" and "wrong password" Allows attackers to determine if an email is registered Always the same message: "Incorrect email or password"

Conclusion

Implementing a secure login and registration is not complex if you follow basic security principles: password hashing, using prepared SQL statements, server-side validation, and protection against XSS attacks. These components are the foundation of every secure web application.

For a detailed example of forms, validation, and password protection in PHP, check out the tutorial: PHP Forms with Secure Processing and Password Protection.

back Back to blog