Theo nội dung cuộc trò chuyện trong phần nhận xét, ý bạn muốn nói là băm mật khẩu, không phải mã hóa mật khẩu. Bạn thường làm điều này với muối để ngăn chặn cuộc tấn công của bàn cầu vồng. Lưu trữ mật khẩu dưới dạng muối băm là tiêu chuẩn thực hành tốt nhất khi nói đến việc lưu trữ mật khẩu trong cơ sở dữ liệu.
Kể từ phiên bản 3.2, MongoDB không có hỗ trợ riêng cho băm mật khẩu như một số cơ sở dữ liệu SQL cung cấp, vì vậy bạn sẽ phải triển khai nó trong Java.
Để tạo tài khoản mới hoặc thay đổi mật khẩu của tài khoản hiện có:
- tạo giá trị muối ngẫu nhiên an toàn bằng mật mã với
java.security.SecureRandom
. Lớp này hoạt động giống như trình tạo số ngẫu nhiên tiêu chuẩnjava.util.Random
(đó là một lớp con) nhưng giao dịch hiệu suất để đạt được mức độ không thể đoán trước cao hơn nhiều, vốn cần thiết cho bối cảnh liên quan đến bảo mật. - Tạo một chuỗi bằng cách nối muối và mật khẩu
- Tạo một hàm băm của chuỗi đó bằng một hàm băm an toàn bằng mật mã. Có rất nhiều hàm băm được cung cấp bởi Java, nhưng bạn muốn sử dụng một hàm cố ý khó tính toán để làm chậm kẻ tấn công có quyền truy cập cơ sở dữ liệu đang cố gắng ép buộc các hàm băm của bạn trên cụm siêu máy tính cục bộ của chúng. Một ứng cử viên tốt là thuật toán "PBKDF2WithHmacSHA1" được hỗ trợ bởi
javax.crypto.SecretKeyFactory
lớp học. - Lưu tài liệu vào MongoDB với các trường
username
,password_hash
vàpassword_salt
(tất nhiên cộng với dữ liệu ứng dụng thực tế của bạn). Không lưu mật khẩu ban đầu.
Để truy xuất tài khoản:
- Đọc
username_input
vàpassword_input
người dùng bị cáo buộc đã nhập vào biểu mẫu đăng nhập của bạn. - Truy xuất tài liệu có
username
khớp vớiusername_input
người dùng đã cung cấp. - Lấy
password_salt
trường từ tài liệu đó - Tạo một chuỗi bằng cách nối
password_salt
vàpassword_input
giống như bạn đã làm trước đây. - Tạo một hàm băm của chuỗi đó với cùng một hàm băm an toàn bằng mật mã.
- So sánh hàm băm với
password_hash
trường của tài liệu. Khi nó khớp, người dùng đã nhập đúng mật khẩu.
Ngoài ra, bạn chỉ có thể truy xuất các trường password_hash và password_salt của tài liệu và không tải phần còn lại trước khi người dùng được xác thực, nhưng tôi giả định rằng trong thế giới thực, nó sẽ gây ra nhiều tải hơn so với khả năng lưu. Những lần đăng nhập thành công thường sẽ nhiều hơn những lần đăng nhập không thành công, trừ khi bạn có kẻ tấn công cố gắng cưỡng bức tài khoản. Và trong trường hợp đó, bạn sẽ chặn kẻ tấn công bằng fail2ban hoặc một cơ chế giới hạn đăng nhập khác.