NTM Solutions

Bài đăng nổi bật

🐘 PHP Cơ Bản 8.2 — CẤP ĐỘ TRỨNG🥚

Tự học PHP từ ZERO đến làm web động #laptrinhphpcoban 📘 PHẦN 1 — NHẬP MÔN PHP Bài 00 — Giới thiệu khóa học & cài đặt môi trường PHP là ...

Thứ Ba, 30 tháng 6, 2026

📘 BÀI 30 — PASSWORD HASH TRONG PHP 8.2🔐

🔐 Bảo mật mật khẩu người dùng

Trong website thực tế, việc lưu mật khẩu là một vấn đề cực kỳ quan trọng.

❌ Sai lầm:

$password = "123456";

Lưu trực tiếp mật khẩu vào database.

Nếu database bị lộ → toàn bộ tài khoản bị lộ.

✅ Đúng cách:

PHP cung cấp cơ chế Hash Password để mã hóa một chiều.

Ví dụ:

Mật khẩu:

123456

Sau khi hash:

$2y$10$kL7x9a8Fj2....

Người khác không thể lấy lại mật khẩu gốc.


1️⃣ Hash mật khẩu bằng password_hash()

Cú pháp:

password_hash($password, $algorithm);

Ví dụ:

<?php

$password = "123456";

$hash = password_hash(
    $password,
    PASSWORD_DEFAULT
);


echo $hash;

?>

Kết quả:

$2y$10$....

Mỗi lần chạy sẽ tạo hash khác nhau.

Ví dụ:

Lần 1:

$2y$10$abc123...

Lần 2:

$2y$10$xyz789...

Nhưng PHP vẫn kiểm tra được.


2️⃣ Lưu mật khẩu vào MySQL

Ví dụ bảng users:

idusernamepassword
1admin$2y$10$abc...

Không lưu:

123456

Mà lưu:

$2y$10$abc123....

3️⃣ Kiểm tra mật khẩu với password_verify()

Khi đăng nhập:

Người dùng nhập:

123456

Database chứa:

$2y$10$abc123....

PHP kiểm tra:

<?php

$password_input = "123456";

$password_db = "$2y$10$abc123";


if(
    password_verify(
        $password_input,
        $password_db
    )
){

    echo "Đăng nhập thành công";

}else{

    echo "Sai mật khẩu";

}

?>

Kết quả:

Đăng nhập thành công

4️⃣ Ví dụ Form đăng ký đơn giản

register.php

<?php


$username = $_POST['username'];

$password = $_POST['password'];



$password_hash = password_hash(
    $password,
    PASSWORD_DEFAULT
);



echo $password_hash;


?>

Người dùng nhập:

username:
admin


password:
123456

PHP tạo:

$2y$10$....

5️⃣ Vì sao không dùng md5()?

Ngày xưa:

md5("123456");

Cho ra:

e10adc3949ba59abbe56e057f20f883e

Nhược điểm:

❌ Có thể bị dò bằng rainbow table
❌ Không có salt mạnh
❌ Không phù hợp cho mật khẩu hiện nay

PHP 8.2 khuyến nghị:

password_hash()

6️⃣ PASSWORD_DEFAULT là gì?

PASSWORD_DEFAULT

PHP tự chọn thuật toán mạnh nhất hiện tại.

Ưu điểm:

✅ Không cần nhớ thuật toán
✅ PHP tự nâng cấp bảo mật
✅ Code lâu dài


7️⃣ Kiểm tra hash hiện tại

PHP có:

password_needs_rehash()

Ví dụ:

if(
password_needs_rehash(
$password_hash,
PASSWORD_DEFAULT
)
){

echo "Cần tạo hash mới";

}

Dùng khi hệ thống nâng cấp bảo mật.


8️⃣ Quy trình đăng nhập thực tế

Đăng ký
    |
    |
Nhập password
    |
    |
password_hash()
    |
    |
Lưu MySQL


----------------


Đăng nhập

Nhập password

    |

password_verify()

    |

Đúng → tạo session

Sai → báo lỗi

🎯 Bài tập thực hành

Tạo hệ thống:

📌 register.php

  • Nhập username

  • Nhập password

  • Hash password

  • Lưu MySQL

📌 login.php

  • Nhập username

  • Nhập password

  • Kiểm tra password_verify()

  • Tạo session


🔐Ví dụ register full

<?php
//register.php

require_once("config.php");

if (isset($_POST['btnsubmit'])) {

    $username = trim($_POST['username']);
    $password = $_POST['password'];
    $hoten    = trim($_POST['hoten']);
    $tuoi     = (int)$_POST['tuoi'];

    // Tạo mật khẩu đã mã hóa
    $password_hash = password_hash(
        $password,
        PASSWORD_DEFAULT
    );

    // Chuẩn bị câu lệnh SQL
    $sql = "
    INSERT INTO users(username, password, hoten, tuoi)
    VALUES (?, ?, ?, ?)
    ";

    $stmt = mysqli_prepare($conn, $sql);

    mysqli_stmt_bind_param(
        $stmt,
        "sssi",
        $username,
        $password_hash,
        $hoten,
        $tuoi
    );

    mysqli_stmt_execute($stmt);

    mysqli_stmt_close($stmt);

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

<form action="" method="post">

    Nhập user name:
    <input type="text" name="username" required>
    <br><br>

    Nhập mật khẩu:
    <input type="password" name="password" required>
    <br><br>

    Nhập họ tên:
    <input type="text" name="hoten" required>
    <br><br>

    Nhập tuổi:
    <input type="number" name="tuoi" min="1" max="120" required>
    <br><br>

    <button type="submit" name="btnsubmit">
        Đăng ký
    </button>

</form>

🎯Mô hình đăng nhập full

  • ✅ Prepared Statement

  • password_verify()

  • password_needs_rehash()

  • session_regenerate_id(true)

  • ✅ Tạo Session

  • ✅ Chuyển sang dashboard.php

  • exit; sau header()

📄 login.php

<?php
/*
===========================================
login.php
===========================================

- Đăng nhập
- password_verify()
- Session
- Session Fixation Protection
*/

session_start();

require_once "config.php";

$message = "";

if (isset($_POST["btnLogin"])) {

    $username = trim($_POST["username"]);
    $password = $_POST["password"];

    $sql = "
        SELECT *
        FROM users
        WHERE username = ?
        LIMIT 1
    ";

    $stmt = mysqli_prepare($conn, $sql);

    mysqli_stmt_bind_param(
        $stmt,
        "s",
        $username
    );

    mysqli_stmt_execute($stmt);

    $result = mysqli_stmt_get_result($stmt);

	//dùng SELECT WHERE lấy đúng username
    if (mysqli_num_rows($result) == 0) {

        $message = "❌ Username không tồn tại.";

    } else {

        $user = mysqli_fetch_assoc($result);
        
		//so sánh password của username đó
        if (
            password_verify(
                $password,
                $user["password"]
            )
        ) {

            // Hash cũ?
            if (
                password_needs_rehash(
                    $user["password"],
                    PASSWORD_DEFAULT
                )
            ) {

                $newHash = password_hash(
                    $password,
                    PASSWORD_DEFAULT
                );

                $sqlUpdate = "
                    UPDATE users
                    SET password=?
                    WHERE id=?
                ";

                $stmtUpdate = mysqli_prepare(
                    $conn,
                    $sqlUpdate
                );

                mysqli_stmt_bind_param(
                    $stmtUpdate,
                    "si",
                    $newHash,
                    $user["id"]
                );

                mysqli_stmt_execute($stmtUpdate);
            }

            // Chống Session Fixation
            session_regenerate_id(true);

            $_SESSION["user_id"] = $user["id"];
            $_SESSION["username"] = $user["username"];

            header("Location: dashboard.php");
            exit;

        } else {

            $message = "❌ Sai mật khẩu.";

        }

    }

}
?>

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>Login</title>

</head>

<body>

<h2>Đăng nhập</h2>

<?php
if ($message != "") {
    echo "<p>$message</p>";
}
?>

<form method="post">

    Username

    <br>

    <input
        type="text"
        name="username"
        required
    >

    <br><br>

    Password

    <br>

    <input
        type="password"
        name="password"
        required
    >

    <br><br>

    <button
        type="submit"
        name="btnLogin"
    >
        Đăng nhập
    </button>

</form>

</body>

</html>

📄 dashboard.php

<?php

session_start();

if (!isset($_SESSION["user_id"])) {

    header("Location: login.php");
    exit;

}

?>

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>Dashboard</title>

</head>

<body>

<h1>Dashboard</h1>

Xin chào

<strong>

<?= htmlspecialchars($_SESSION["username"]) ?>

</strong>

<br><br>

<a href="logout.php">

Đăng xuất

</a>

</body>

</html>

📄 logout.php

<?php

session_start();

// Xóa toàn bộ session
$_SESSION = [];

// Hủy session
session_destroy();

// Quay về trang login
header("Location: login.php");
exit;

📂 Cấu trúc thư mục

project/

│ config.php
│ login.php
│ dashboard.php
│ logout.php

└── users

Đây cũng chính là mô hình đăng nhập cơ bản mà hầu hết các framework PHP (như Laravel, CodeIgniter, Symfony) đều triển khai với các bước:

  1. Nhập username/password.

  2. Truy vấn người dùng theo username.

  3. password_verify() để kiểm tra mật khẩu.

  4. session_regenerate_id(true) để tăng cường bảo mật.

  5. Lưu thông tin cần thiết vào $_SESSION.

  6. Chuyển hướng đến trang được bảo vệ.

  7. Kiểm tra $_SESSION ở mọi trang cần đăng nhập.

  8. logout.php xóa session và quay lại trang đăng nhập.

✅ Sau bài 30 bạn hiểu:

✔ Vì sao không lưu mật khẩu dạng text
✔ password_hash()
✔ password_verify()
✔ Bảo mật đăng nhập cơ bản
✔ Chuẩn bị xây dựng hệ thống user thực tế

📚 Bài tiếp theo:
🐘 Bài 31 — Filter dữ liệu trong PHP
(kiểm tra, làm sạch dữ liệu trước khi lưu database)

x1

quay về MỤC LỤC

Không có nhận xét nào:

Đăng nhận xét

Facebook Youtube RSS