Skip to content

PHP Tutorial PHP Security

Password Security

Lesson 298 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

Passwords are the keys to your users’ accounts. A short list of rules, with links to the lessons that explain each.

Storing passwords

  • Hash with password_hash() and PASSWORD_DEFAULT. See password_hash().
  • Verify with password_verify(), and upgrade with password_needs_rehash(). See password_verify().
  • Never use md5(), sha1(), sha256() or a home-made scheme.
  • Never store, log, email or display a plain password.
index.php
PHP
<?php
function storePassword(#[\SensitiveParameter] string $password): string
{
    return password_hash($password, PASSWORD_DEFAULT);
}

$hash = storePassword("correct horse battery staple");

echo str_starts_with($hash, '$2y$') ? "hashed" : "not hashed";
Output
OUTPUT
hashed

The #[\SensitiveParameter] attribute (PHP 8.2+) tells PHP to hide this argument in stack traces, so it does not appear in logs if an exception happens.

Choosing a policy

  • Minimum length of 8 to 12 characters or more.
  • Allow all characters and long passphrases.
  • No arbitrary composition rules, no forced regular changes.
  • Reject passwords that appear in lists of known leaked passwords.
  • Show a strength hint, but do not rely on it.
index.php
PHP
<?php
function passwordProblems(string $password, string $email): array
{
    $problems = [];

    if (mb_strlen($password) < 10) {
        $problems[] = "Use at least 10 characters.";
    }

    if (strtolower($password) === strtolower($email) || str_contains(strtolower($password), "password")) {
        $problems[] = "Do not use your email or the word \"password\".";
    }

    return $problems;
}

print_r(passwordProblems("password123", "isha@example.com"));
Output
OUTPUT
Array
(
    [0] => Do not use your email or the word "password".
)

In the form

  • <input type="password" autocomplete="new-password"> when creating one, autocomplete="current-password" when logging in.
  • Do not block paste. Password managers rely on it.
  • Do not put the password back in the field after an error.

Transport

  • HTTPS only, for the form and the whole site.
  • Use POST, never put passwords in a URL.

Reset and change

  • Reset tokens are random, hashed in the database, short-lived and used once. See Password Reset.
  • Ask for the current password when changing the password or email.
  • After a change: end other sessions, delete remember-me tokens and email the user.

Protect the login form

  • Rate limit attempts, and slow down repeated failures.
  • One generic error message.
  • Offer two-factor authentication.

Never email a password

If you can email a user their password, you stored it in plain text or reversibly. A forgotten password is always reset, never recovered.

Admin accounts

  • Unique, long passwords for hosting, database and admin panels, stored in a password manager.
  • Two-factor authentication on hosting, Git and email accounts.
info
Why this matters in WordPress
Weak and reused passwords are among the most common reasons for hacked WordPress sites. Strong passwords, two-factor authentication and login limits matter as much as your code.