Để sử dụng session tạo form đăng ký, đăng nhập người dùng có sử dụng mã hóa cho ô mật khẩu cần tạo bảng cơ sở dữ liệu người dùng và tạo file code đăng ký, đăng nhập và trang chuyển hướng khi đăng nhập thành công.
Tạo Bảng User có cấu trúc như sau:
Trong bảng này, bạn tạo các cột dữ liệu: Id, HoTen, User, Pass.
Tạo file kết nối connection.php nội dung như sau:
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
die("Kết nối thất bại: " . $conn->connect_error);
}
?>
Tạo file đăng ký dangky.php có nội dung như sau:
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Đăng ký tài khoản</title>
<link rel="stylesheet" href="css/user.css">
</head>
<body>
<div class="mycontainer">
<h2>Đăng ký tài khoản</h2>
<form action="process_registration.php" method="POST">
<div class="imgcontainer">
<img src="images/avatar.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label for="fullname">Họ và tên:</label><br>
<input type="text" id="fullname" name="fullname" required><br>
<label for="username">Tên người dùng:</label><br>
<input type="text" id="username" name="username" required><br>
<label for="password">Mật khẩu:</label><br>
<input type="password" id="password" name="password" required><br>
<button type="submit">Đăng ký</button>
</div>
</form>
</div>
</body>
</html>
Tạo file xử lý đăng ký process_registration.php nội dung như sau:
<?php
include "connection.php";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$fullname = mysqli_real_escape_string($conn, $_POST["fullname"]);
$username = mysqli_real_escape_string($conn, $_POST["username"]);
$password = mysqli_real_escape_string($conn, $_POST["password"]);
// Mã hóa mật khẩu bằng Argon2. Các thuật toán băm mật khẩu mạnh mẽ như bcrypt hoặc Argon2
$hashed_password = password_hash($password, PASSWORD_ARGON2I);
// hoặc bạn cũng có thể dùng $hashed_password = password_hash($password, PASSWORD_BCRYPT);
$sql = "INSERT INTO user (HoTen, User, Pass) VALUES ('$fullname', '$username', '$hashed_password')";
if ($conn->query($sql) === TRUE) {
echo "Đăng ký tài khoản thành công.";
// Chuyển hướng đến trang chính hoặc trang đăng nhập sau khi đăng ký thành công
// header("Location: login.php");
// exit();
} else {
echo "Lỗi: " . $conn->error;
}
}
$conn->close();
?>
Tạo file đăng nhập login.php nội dung như sau:
<?php
// Khởi động session
session_start();
// Kiểm tra xem người dùng đã submit form hay chưa
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Kết nối đến cơ sở dữ liệu
include "connection.php";
// Lấy tên đăng nhập và mật khẩu từ form
$uname = mysqli_real_escape_string($conn, $_POST['uname']);
$psw = mysqli_real_escape_string($conn, $_POST['psw']);
// Lấy thông tin người dùng từ cơ sở dữ liệu
$sql = "SELECT * FROM user WHERE User='$uname'";
$result = $conn->query($sql);
if ($result->num_rows == 1) {
// Lấy mật khẩu đã băm từ kết quả truy vấn
$row = $result->fetch_assoc();
$hashed_password = $row['Pass'];
// Kiểm tra mật khẩu đã băm với mật khẩu nhập vào bằng hàm password_verify
if (password_verify($psw, $hashed_password)) {
// Lưu trạng thái đăng nhập vào session
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $uname;
// Chuyển hướng người dùng đến trang giaodienchinh.php
header('Location: giaodienchinh.php');
exit;
} else {
// Nếu mật khẩu không chính xác, hiển thị thông báo lỗi
$error = "Tên đăng nhập hoặc mật khẩu không chính xác.";
}
} else {
// Nếu không tìm thấy người dùng, hiển thị thông báo lỗi
$error = "Tên đăng nhập hoặc mật khẩu không chính xác.";
}
// Đóng kết nối MySQL
$conn->close();
}
?>
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Đăng ký tài khoản</title>
<link rel="stylesheet" href="css/user.css">
</head>
<div class="mycontainer">
<?php
// Hiển thị thông báo lỗi nếu có
if (isset($error)) {
echo "<p>$error</p>";
}
?>
<h2>Login Form</h2>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<div class="imgcontainer">
<img src="images/avatar.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label for="uname"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="uname" required>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" required>
<button type="submit">Login</button>
<label>
<input type="checkbox" checked="checked" name="remember"> Remember me
</label>
</div>
</form>
</div>
</body>
</html>
Tạo file giao diện chính khi đăng nhập thành công giaodienchinh.php như sau:
<?php
// Khởi động session
session_start();
// Kiểm tra xem người dùng đã đăng nhập hay chưa
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
// Nếu chưa đăng nhập, chuyển hướng người dùng đến trang đăng nhập
header('Location: login.php');
exit;
}
?>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Đăng ký tài khoản</title>
<link rel="stylesheet" href="css/user.css">
</head>
<body>
<div class="mycontainer">
<h2>Nội dung giao diện chính ở đây</h2>
<p>Xin chào <?php echo $_SESSION['username'] . "!";?></p>
<a href="logout.php">Đăng xuất</a>
</div>
</body>
</html>
Tạo file đăng xuất thoát khỏi hệ thống logout.php như sau:
<?php
// Bắt đầu hoặc tiếp tục phiên làm việc
session_start();
// Xoá tất cả các biến phiên làm việc
$_SESSION = array();
// Nếu có cookie liên kết với phiên làm việc, hủy cookie
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// Hủy phiên làm việc
session_destroy();
// Chuyển hướng về trang chính hoặc trang đăng nhập
header("Location: login.php");
exit;
?>
Tạo file user.css trong thư mục css có nội dung như sau:
body {font-family: Arial, Helvetica, sans-serif;}
form {border: 3px solid #f1f1f1;}
.mycontainer{ width:500px; margin-left: auto; margin-right:auto;}
input[type=text], input[type=password] {
width: 100%; padding: 12px 20px; margin: 8px 0; display: inline-block;
border: 1px solid #ccc; box-sizing: border-box;}
button {background-color: #04AA6D; color: white; padding: 14px 20px;
margin: 8px 0; border: none; cursor: pointer; width: 100%;}
button:hover { opacity: 0.8;}
.cancelbtn { width: auto; padding: 10px 18px; background-color: #f44336;}
.imgcontainer { text-align: center; margin: 24px 0 12px 0;}
img.avatar { width: 40%; border-radius: 50%;}
.container { padding: 16px;}
span.psw { float: right; padding-top: 16px;}
/* Change styles for span and cancel button on extra small screens */
@media screen and (max-width: 300px) {
span.psw { display: block; float: none; }
.cancelbtn { width: 100%; }
}
Kết quả: Chạy và mô tả kết quả
Giao diện chạy file đăng ký người dùng dangky.php:
Giao diện khi chạy file đăng nhập login.php:
Một vài lưu ý quan trọng khi tạo form đăng nhập, đăng ký người dùng
Lưu ý về sử dụng hàm mysqli_real_escape_string
Hàm mysqli_real_escape_string()
trong PHP được sử dụng để “chống” các cuộc tấn công SQL Injection bằng cách làm sạch các ký tự đặc biệt từ chuỗi truy vấn trước khi thực hiện truy vấn đến cơ sở dữ liệu MySQL.
Khi bạn xây dựng một truy vấn SQL từ dữ liệu người dùng, đặc biệt là từ các trường nhập liệu như biểu mẫu HTML, có nguy cơ mà người dùng có thể chèn các câu lệnh SQL độc hại vào các trường này. Điều này có thể dẫn đến việc thực thi các truy vấn SQL không mong muốn và tiềm ẩn nguy cơ lớn cho bảo mật hệ thống.
Hàm mysqli_real_escape_string()
nhận một chuỗi làm đối số và trả về một phiên bản của chuỗi đó với các ký tự đặc biệt đã được “escape” (hoặc thay thế) sao cho chúng không được hiểu là phần của câu lệnh SQL. Điều này giúp ngăn chặn các cuộc tấn công SQL Injection bằng cách biến các ký tự đặc biệt như dấu nháy đơn, dấu nháy kép, dấu gạch chéo, vv. thành các chuỗi thoái mái vô hại đối với cú pháp SQL.
Lưu ý về sử dụng session để quản lý phiên đăng nhập
Việc sử dụng session để quản lý phiên đăng nhập trong hệ thống có một số ưu điểm và nhược điểm như sau:
Ưu điểm:
- Đơn giản: Sử dụng session là một cách đơn giản để quản lý phiên đăng nhập. PHP cung cấp các hàm sẵn có để bắt đầu, lưu trữ và hủy phiên làm việc một cách dễ dàng.
- Hiệu suất tốt: Session lưu trữ thông tin trên máy chủ và chỉ gửi một ID phiên cho người dùng qua cookie. Do đó, việc lưu trữ thông tin đăng nhập trong session có thể tăng hiệu suất so với lưu trữ trên cookie hoặc cơ sở dữ liệu.
- Bảo mật: Dữ liệu được lưu trữ trong session không được lưu trữ trên máy khách (trình duyệt), điều này làm giảm nguy cơ bị lộ thông tin đăng nhập.
Nhược điểm:
- Khả năng tấn công: Phiên làm việc có thể bị tấn công bằng cách chiếm quyền truy cập vào phiên của người dùng, ví dụ như bằng cách chiếm quyền truy cập vào cookie phiên.
- Quản lý phiên: Trong một ứng dụng lớn, việc quản lý các phiên làm việc có thể trở nên phức tạp, đặc biệt là khi cần theo dõi và hủy các phiên không hoạt động.
- Chia sẻ trạng thái đăng nhập giữa các máy chủ: Trong một môi trường phân tán, việc chia sẻ trạng thái đăng nhập qua các máy chủ có thể trở thành vấn đề.
- Tiêu tốn tài nguyên máy chủ: Session cần phải lưu trữ trên máy chủ, điều này có thể tạo áp lực lên tài nguyên máy chủ đặc biệt khi có nhiều người dùng cùng thời điểm.
Tóm lại, việc sử dụng session để quản lý phiên đăng nhập là một cách tiện lợi và phổ biến, nhưng cần phải cân nhắc và áp dụng các biện pháp bảo mật phù hợp để đảm bảo tính an toàn và bảo mật của hệ thống.
Lưu ý về sử dụng password_hash và password_verify
Dưới đây là một số lưu ý quan trọng khi sử dụng password_hash()
và password_verify()
trong PHP để xử lý mật khẩu:
1. Sử dụng password_hash()
để mã hóa mật khẩu:
- Luôn sử dụng hàm
password_hash()
để băm mật khẩu trước khi lưu trữ nó vào cơ sở dữ liệu. Hàm này sẽ sử dụng một thuật toán băm mật khẩu an toàn như bcrypt hoặc Argon2 để tạo một bản băm mật khẩu có độ dài an toàn và không thể đoán được. - Không sử dụng các thuật toán băm mật khẩu cũ như MD5 hoặc SHA1 vì chúng không còn an toàn.
2. Sử dụng password_verify()
để kiểm tra mật khẩu:
- Khi người dùng đăng nhập, sử dụng hàm
password_verify()
để so sánh mật khẩu nhập vào với mật khẩu đã được băm trong cơ sở dữ liệu. - Hàm
password_verify()
sẽ kiểm tra xem mật khẩu nhập vào có khớp với mật khẩu đã băm hay không mà không cần phải lưu trữ mật khẩu dưới dạng văn bản rõ. - Điều này giúp bảo vệ mật khẩu của người dùng, ngay cả khi cơ sở dữ liệu của bạn bị tấn công.
3. Đảm bảo lưu trữ độ dài của bản băm:
- Đảm bảo rằng trường trong cơ sở dữ liệu được sử dụng để lưu trữ mật khẩu băm có độ dài đủ lớn để chứa bản băm mật khẩu.
- Khuyến khích sử dụng kiểu dữ liệu dài đủ như VARCHAR(255) để lưu trữ bản băm mật khẩu.
4. Không lưu trữ mật khẩu dưới dạng văn bản rõ:
- Tránh lưu trữ mật khẩu dưới dạng văn bản rõ trong cơ sở dữ liệu hoặc bất kỳ nơi nào khác.
- Việc lưu trữ mật khẩu dưới dạng văn bản rõ là một lỗ hổng bảo mật lớn và có thể dẫn đến việc bị tấn công nếu cơ sở dữ liệu bị đánh cắp.
Bằng cách tuân thủ các lưu ý này, bạn có thể đảm bảo rằng việc xử lý mật khẩu trong ứng dụng của bạn là an toàn và bảo mật.