PHP MySQL password hashing
In PHP MySQL procedural style, using password_hash()
is essential for securely storing passwords in the database. This function provides a strong one-way encryption that makes it virtually impossible to reverse the hashed password into its original form, ensuring the security of stored passwords.
What is password_hash()
?
password_hash()
is a built-in PHP function that hashes passwords using strong and secure algorithms. By default, it uses the Bcrypt algorithm, but newer versions of PHP support Argon2 as well.
Key features:
- Automatically generates a salt (random data added to the password before hashing).
- Uses a cost factor, which defines the computational complexity of the hashing algorithm.
- Compatible with
password_verify()
to check if a given password matches the stored hash.
How password_hash()
Works
- Hashing the password: Convert the plain-text password into a hashed string before saving it to the database.
- Verifying the password: When a user logs in, the plain-text password they provide is compared against the hashed password stored in the database using
password_verify()
.
Syntax of password_hash()
password_hash(string $password, int $algo, array $options = [])
$password
: The plain-text password to be hashed.$algo
: The algorithm used (e.g.,PASSWORD_DEFAULT
,PASSWORD_BCRYPT
).$options
: An optional array of options likecost
(higher cost makes it harder to brute-force but slower to compute).
Example: Registering a User with password_hash()
Let’s create a simple example of how to hash passwords using password_hash()
and store them in a MySQL database.
Step 1: Create the Registration Form
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Registration</title>
</head>
<body>
<h2>User Registration</h2>
<form action="register.php" method="POST">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required><br><br>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required><br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required><br><br>
<input type="submit" value="Register">
</form>
</body>
</html>
Step 2: PHP Code to Handle Registration and Hash the Password (register.php
)
<?php
// Check if the form was submitted
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Step 1: Capture the input data and sanitize
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = trim($_POST['password']);
$username = filter_var($username, FILTER_SANITIZE_STRING);
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
// Step 2: Validate input data
if (empty($username) || empty($email) || empty($password)) {
die("All fields are required.");
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die("Invalid email format.");
}
// Step 3: Hash the password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Step 4: Connect to MySQL
$conn = mysqli_connect("localhost", "root", "", "test_db");
// Check the connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
// Step 5: Prepare the SQL query
$sql = "INSERT INTO users (username, email, password) VALUES ('$username', '$email', '$hashed_password')";
// Step 6: Execute the query and insert data
if (mysqli_query($conn, $sql)) {
echo "User registered successfully!";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
// Close the connection
mysqli_close($conn);
}
?>
Step-by-Step Breakdown:
User Inputs:
- The form collects the
username
,email
, andpassword
. - PHP retrieves the inputs using the
$_POST
superglobal and sanitizes them usingfilter_var()
.
- The form collects the
Hash the Password:
- The password entered by the user is hashed using
password_hash($password, PASSWORD_DEFAULT)
. - The
PASSWORD_DEFAULT
constant ensures that PHP uses the best available hashing algorithm (currently Bcrypt). - The hashed password is a long string that contains both the salt and the hashed password.
- The password entered by the user is hashed using
Insert the User Data:
- The hashed password, along with the username and email, is inserted into the MySQL database.
- The password is stored as a hashed value, ensuring that even if the database is compromised, the passwords remain secure.
Step 3: Create the Database Table
Create a users
table in MySQL to store user registration information.
CREATE DATABASE test_db;
USE test_db;
CREATE TABLE users (
id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Verifying the Password During Login
When a user logs in, you'll need to verify the entered password against the stored hashed password. This is done using the password_verify()
function.
Example: Login Script (login.php
)
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = trim($_POST['email']);
$password = trim($_POST['password']);
// Sanitize email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
// Connect to MySQL
$conn = mysqli_connect("localhost", "root", "", "test_db");
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
// Retrieve the stored hashed password for the user
$sql = "SELECT * FROM users WHERE email = '$email'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) == 1) {
$user = mysqli_fetch_assoc($result);
$hashed_password = $user['password'];
// Step 1: Verify the entered password against the stored hashed password
if (password_verify($password, $hashed_password)) {
echo "Login successful!";
// Start a session or redirect the user
} else {
echo "Invalid password.";
}
} else {
echo "User not found.";
}
mysqli_close($conn);
}
?>
Password Verification:
- Retrieve User: The script retrieves the user’s record from the database based on the provided email.
- Verify Password: The
password_verify($password, $hashed_password)
function checks if the entered plain-text password matches the hashed password stored in the database. - Handle Result: If the password is correct, the user is logged in. If not, an error message is displayed.
Benefits of password_hash()
and password_verify()
:
- Automatic Salting:
password_hash()
generates a random salt automatically, making the same password produce a different hash each time. - Strong Hashing: The default algorithm (
PASSWORD_DEFAULT
, currently Bcrypt) is designed to be slow to defend against brute-force attacks. - Future-proof: The
PASSWORD_DEFAULT
constant automatically upgrades to stronger algorithms as they become available in future PHP versions, without needing to modify your code.