Hỗ trợ đồ án, khóa luận Web, App, AI - Uy tín, chất lượng!
Hỗ trợ đồ án, khóa luận Web, App, AI - Uy tín, chất lượng!
Trang Chủ Hướng Dẫn Đồ Án Hash mật khẩu bằng password_hash trong PHP
Hướng Dẫn Đồ ÁnLập Trình Web

Hash mật khẩu bằng password_hash trong PHP

Chia sẻ
Chia sẻ

Trong lập trình web, bảo mật tài khoản người dùng luôn là một trong những yêu cầu quan trọng nhất. Nếu bạn xây dựng một hệ thống đăng nhập mà lưu mật khẩu dạng plain text (nguyên gốc) trong cơ sở dữ liệu, đó sẽ là sai lầm nghiêm trọng. Bởi chỉ cần kẻ tấn công xâm nhập vào cơ sở dữ liệu, toàn bộ tài khoản người dùng sẽ bị lộ ngay lập tức.

Để tránh rủi ro này, PHP cung cấp sẵn hàm password_hash() để hash (mã hóa một chiều) mật khẩu và password_verify() để xác minh mật khẩu khi người dùng đăng nhập. Đây là giải pháp an toàn, hiện đại và dễ sử dụng, thay thế cho các cách làm cũ như md5() hoặc sha1(), vốn không còn đủ mạnh trước các kỹ thuật tấn công hiện nay.

Nếu bạn đã tìm hiểu qua các bài trước như:

thì việc kết hợp với password_hashpassword_verify sẽ giúp bạn xây dựng được một hệ thống đăng nhập và quản lý người dùng vừa an toàn vừa chuyên nghiệp.

Tại sao không nên lưu mật khẩu gốc?

Một trong những sai lầm phổ biến nhất của lập trình viên mới là lưu mật khẩu gốc (plain text) trong database. Ví dụ, bảng users chứa cột password với giá trị "123456" hoặc "abc123". Điều này vô cùng nguy hiểm vì:

  • Nếu database bị rò rỉ, kẻ tấn công sẽ biết toàn bộ mật khẩu ngay lập tức.

  • Người dùng thường dùng chung một mật khẩu cho nhiều dịch vụ, do đó hệ quả không chỉ dừng lại ở website của bạn.

  • Website dễ bị mất uy tín và có thể vi phạm các quy định về bảo mật dữ liệu.

Chính vì vậy, quy tắc cơ bản là không bao giờ lưu mật khẩu gốc. Thay vào đó, ta cần hash mật khẩu để khi database bị lộ, kẻ tấn công cũng khó (hoặc gần như không thể) giải mã lại mật khẩu ban đầu.

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

PHP cung cấp hàm password_hash() để mã hóa mật khẩu một cách an toàn. Hàm này sử dụng các thuật toán mạnh như bcrypt, argon2i, hoặc argon2id.

Trước tiên, hãy hiểu cách hoạt động:

  • Khi người dùng đăng ký, bạn nhận mật khẩu từ form.

  • Thay vì lưu trực tiếp mật khẩu, bạn hash nó bằng password_hash().

  • Chuỗi hash này sẽ được lưu vào database.

  • Khi người dùng đăng nhập, bạn sẽ dùng password_verify() để so sánh.

Ví dụ cách hash:

<?php
$password = "123456"; // mật khẩu người dùng nhập khi đăng ký
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

echo $hashedPassword;
?>

Trong đoạn code này, biến $hashedPassword sẽ chứa một chuỗi dài, ví dụ:

$2y$10$KsvkVn9OaqS1Z5UwJ7X2xuzxN1vV6t9JG/nV6r3zdsZoJ0u6cR6i6

Chuỗi này bao gồm cả thông tin về thuật toán, độ mạnh (cost) và giá trị salt ngẫu nhiên. Điều này giúp mỗi lần hash cùng một mật khẩu vẫn ra kết quả khác nhau, tăng cường bảo mật.

Lưu mật khẩu đã hash vào database

Sau khi có mật khẩu hash, chúng ta cần lưu nó vào database thay vì mật khẩu gốc. Ở đây, PDO sẽ rất hữu ích để thực hiện truy vấn an toàn.

Ví dụ đoạn code lưu mật khẩu khi đăng ký:

<?php
$pdo = new PDO("mysql:host=localhost;dbname=mydb;charset=utf8", "root", "");

// Mật khẩu gốc từ form đăng ký
$password = $_POST['password'];

// Hash mật khẩu
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

// Lưu vào database
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password)");
$stmt->execute([
    ':username' => $_POST['username'],
    ':password' => $hashedPassword
]);
?>

Trong đoạn code trên:

  • password_hash() tạo ra mật khẩu hash.

  • PDO được dùng để tránh SQL Injection.

  • Bảng users sẽ lưu giá trị hash chứ không phải mật khẩu gốc.

Xác minh mật khẩu bằng password_verify()

Khi người dùng đăng nhập, ta không thể so sánh trực tiếp mật khẩu nhập vào với giá trị hash trong database, vì mỗi lần hash sẽ ra một chuỗi khác nhau. Thay vào đó, PHP cung cấp hàm password_verify() để xác minh.

Ví dụ:

<?php
// Mật khẩu người dùng nhập khi đăng nhập
$passwordInput = $_POST['password'];

// Lấy mật khẩu hash từ database
$stmt = $pdo->prepare("SELECT password FROM users WHERE username = :username");
$stmt->execute([':username' => $_POST['username']]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

if ($row && password_verify($passwordInput, $row['password'])) {
    echo "Đăng nhập thành công";
} else {
    echo "Sai tên đăng nhập hoặc mật khẩu";
}
?>

Ở đây, password_verify() sẽ tự động hash mật khẩu nhập vào bằng cùng thuật toán và salt đã dùng khi lưu trữ, sau đó so sánh với chuỗi hash trong database. Nếu trùng khớp, xác minh thành công.

Kết hợp với Session để quản lý đăng nhập

Sau khi xác minh thành công bằng password_verify(), bước tiếp theo là sử dụng Session để quản lý trạng thái đăng nhập. Đây là kỹ thuật đã đề cập chi tiết trong bài Giữ đăng nhập bằng Session trong PHP.

Ví dụ:

<?php
session_start();

if ($row && password_verify($passwordInput, $row['password'])) {
    $_SESSION['username'] = $_POST['username'];
    header("Location: dashboard.php");
    exit;
}
?>

Cách làm này giúp bạn dễ dàng kiểm tra quyền truy cập của người dùng ở các trang khác.

So sánh password_hash với md5 và sha1

Trước đây, nhiều lập trình viên hay dùng md5() hoặc sha1() để mã hóa mật khẩu. Tuy nhiên, cả hai thuật toán này đã lỗi thời vì dễ bị tấn công brute force và rainbow table.

Ví dụ:

md5("123456"); // e10adc3949ba59abbe56e057f20f883e
sha1("123456"); // 7c4a8d09ca3762af61e59520943dc26494f8941b

Trong khi đó, password_hash() dùng các thuật toán hiện đại như bcrypt hoặc Argon2, có tích hợp salt và cost, giúp an toàn hơn rất nhiều. Vì vậy, không bao giờ nên dùng md5 hoặc sha1 để bảo mật mật khẩu trong ứng dụng web.

Cập nhật hash khi cần thiết

Một lợi thế khác của password_hash() là bạn có thể kiểm tra xem hash hiện tại có cần nâng cấp hay không (ví dụ khi muốn tăng cost hoặc đổi thuật toán). Hàm password_needs_rehash() sẽ giúp bạn làm việc này.

Ví dụ:

<?php
if (password_needs_rehash($row['password'], PASSWORD_DEFAULT, ['cost' => 12])) {
    $newHash = password_hash($passwordInput, PASSWORD_DEFAULT, ['cost' => 12]);
    // Cập nhật lại mật khẩu hash trong DB
}
?>

Nhờ vậy, bạn có thể nâng cấp bảo mật hệ thống mà không ảnh hưởng tới trải nghiệm người dùng.

Kết luận

Qua bài viết này, bạn đã hiểu cách sử dụng password_hash() để mã hóa mật khẩupassword_verify() để xác minh khi đăng nhập. Đây là phương pháp an toàn, hiện đại, thay thế cho các hàm cũ như md5 hoặc sha1.

Khi kết hợp với PDO, Session, CRUD và các kỹ thuật khác, bạn sẽ có thể xây dựng một hệ thống đăng nhập bảo mật, chuyên nghiệp và dễ dàng mở rộng. Bảo mật mật khẩu người dùng là bước đầu tiên và quan trọng nhất để bảo vệ uy tín của website cũng như quyền lợi của khách hàng.

Tham Gia Nhóm – Hỗ Trợ Lập Trình

Hỗ Trợ Đồ Án – ThueDoAn.vn

Liên quan
Hướng Dẫn Đồ Án

Checklist 10 bước kiểm tra cuối cùng trước khi nhấn nút nộp đồ án

Thời điểm chuẩn bị nhấn nút nộp đồ án luôn mang lại...

Hướng Dẫn Đồ Án

Tuyệt chiêu đối phó với những giảng viên hướng dẫn ‘khó tính’ nhất

Giai đoạn làm đồ án tốt nghiệp luôn đi kèm với vô...

Hướng Dẫn Đồ Án

Tại sao việc quản lý Source Code bằng Git lại quan trọng hơn bạn nghĩ?

Trong thế giới lập trình hiện đại, mã nguồn chính là linh...

Hướng Dẫn Đồ Án

Những chức năng ‘thừa’ khiến bạn tốn thời gian mà không được cộng điểm

Làm đồ án tốt nghiệp là một cuộc đua thực thụ với...

Hướng Dẫn Đồ Án

Cách xử lý khi đề tài bị trùng lặp ý tưởng với các khóa trước quá nhiều

Lựa chọn đề tài đồ án luôn là bước khởi đầu đầy...

Hướng Dẫn Đồ Án

Làm sao để giải trình với giảng viên khi code bị nghi ngờ là đi chép?

Trong quá trình thực hiện đồ án, việc tham khảo mã nguồn...

Hướng Dẫn Đồ Án

Cảnh báo: Những nguồn share code ‘rác’ trên mạng cần tuyệt đối tránh

Trong quá trình làm đồ án, việc tìm kiếm sự hỗ trợ...

Hướng Dẫn Đồ Án

Sai lầm khi chọn công nghệ quá khó so với năng lực thực tế của bản thân

Chọn đề tài và công nghệ cho đồ án luôn là bước...

Liên Hệ
Liên hệ để được tư vấn & hỗ trợ đồ án CNTT nhé bạn!