Tôi thấy bạn đang lưu trữ một hàm băm của mật khẩu trong cơ sở dữ liệu, nhưng vì lợi ích của những người đọc khác, không bao giờ lưu trữ mật khẩu dưới dạng văn bản thuần túy trong cơ sở dữ liệu. Bạn không muốn trở thành như Monster.com.uk !
Bạn nên sử dụng hàm băm mạnh hơn MD5()
. Tốt nhất bạn nên sử dụng SHA256. Phương thức băm này có sẵn trong PHP bằng cách sử dụng hash()
chức năng.
Bạn cũng nên áp dụng một muối ngẫu nhiên vào mật khẩu. Lưu trữ một giá trị muối khác nhau cho tài khoản của mỗi người dùng. Điều này giúp đánh bại các cuộc tấn công từ điển và bảng cầu vồng các cuộc tấn công.
Bạn nên học cách sử dụng mysqli tiện ích mở rộng thay cho tiện ích mở rộng mysql cũ. Mysqli hỗ trợ các truy vấn được tham số hóa, vì vậy bạn có thể giảm nguy cơ bị tấn công bởi một số cuộc tấn công SQL injection.
Đây là một số mã ví dụ. Tôi chưa thử nghiệm nó, nhưng nó sẽ khá gần hoạt động:
$input_login = $_POST['login'];
$input_password = $_POST['password'];
$stmt = $mysqli->prepare("SELECT password, salt FROM customer WHERE login = ?");
$stmt->bind_param("s", $input_login);
$stmt->execute();
$stmt->bind_result($password_hash, $salt);
while ($stmt->fetch()) {
$input_password_hash = hash('sha256', $input_password . $salt);
if ($input_password_hash == $password_hash) {
return true;
}
// You may want to log failed password attempts here,
// for security auditing or to lock an account with
// too many attempts within a short time.
}
$stmt->close();
// No rows matched $input_login, or else password did not match
return false;
Một số người khác đề xuất truy vấn nên kiểm tra login = ? AND password = ?
nhưng tôi không thích làm điều đó. Nếu bạn làm điều này, bạn không thể biết liệu tra cứu không thành công do thông tin đăng nhập không tồn tại hay do người dùng cung cấp mật khẩu sai.
Tất nhiên, bạn không nên tiết lộ cho người dùng biết nguyên nhân gây ra nỗ lực đăng nhập không thành công, nhưng bạn có thể cần biết, vì vậy bạn có thể ghi lại hoạt động đáng ngờ.
@Javier nói trong câu trả lời của mình rằng bạn không nên lấy mật khẩu (hoặc băm mật khẩu trong trường hợp này) từ cơ sở dữ liệu. Tôi không đồng ý.
Javier hiển thị đang gọi md5()
trong mã PHP và gửi chuỗi băm kết quả đó đến cơ sở dữ liệu. Nhưng điều này không hỗ trợ việc ướp muối cho mật khẩu một cách dễ dàng. Bạn phải thực hiện một truy vấn riêng để truy xuất muối của người dùng này trước khi bạn có thể thực hiện băm trong PHP.
Giải pháp thay thế là gửi bản rõ mật khẩu qua mạng từ ứng dụng PHP đến máy chủ cơ sở dữ liệu của bạn. Bất kỳ ai nghe lén mạng của bạn đều có thể thấy mật khẩu này. Nếu bạn có các truy vấn SQL đang được ghi nhật ký, bất kỳ ai có quyền truy cập vào nhật ký đều có thể thấy mật khẩu. Các tin tặc có động cơ thậm chí có thể lặn xuống để tìm phương tiện sao lưu hệ thống tệp cũ và có thể đọc các tệp nhật ký theo cách đó!
Rủi ro thấp hơn là tìm nạp chuỗi băm mật khẩu từ cơ sở dữ liệu vào ứng dụng PHP, so sánh nó với chuỗi băm của đầu vào của người dùng (cũng trong mã PHP), sau đó loại bỏ các biến này.