Trong bài viết này, tôi hướng dẫn các bạn tạo 1 mã otp và gửi đến email của chính mình để xác thực cho mỗi lần đăng nhập. Tôi sử dụng MailTrap
Các vấn đề cần xử lý:
- Tạo 1 model Otp, tự động sinh Otp mỗi lần đăng nhập
- Thiết lập thời gian sống của otp
- Gửi mail với mã Otp vừa sinh ra
Công cụ và thư viện được sử dụng trong bài viết:
- Spring boot 2.7.4
- Spring tool suite 4
- Spring data elasticsearch 4.4.2
- Maven 3
- Java 11
- Elasticsearch 7.17.6
- Kaizen Elastic
Tham khảo những bài viết sau để biết cách tạo 1 project với Spring Boot - Thymeleaf - Elasticsearch:
Nguồn template: https://bbbootstrap.com/snippets/bootstrap-mobile-phone-verification-form-using-otp-78737873#
1. Cấu trúc project:
2. Package "com.example.otp.application":
Nội dung class "OtpApplication":
3. Package "com.example.otp.model":
Nội dung class "Otp":
Nội dung class "User":
4. Package "com.example.otp.repository":
Nội dung class "UserRepository":
Nội dung class "OtpRepository":
5. Package "com.example.otp.service":
Nội dung class "IOtpService":
Nội dung class "OtpService":
6. Package "com.example.otp.controller":
7. Application file:
Trong config tôi có enable SSL và HTTP/2, các bạn không cần làm điều này trong bài viết, tham khảo các bài viết ở trên tôi có hướng dẫn cách enable SSL và HTTP/2
Có 4 thuộc tính cần quan tâm là:
-
otp.expired.in: Thuộc tính này dùng để chỉ định thời gian sống cho Otp tính bằng phút
-
otp.max.length: Chỉ định độ dài tối đa của 1 mã otp, ở đây tôi chỉ định otp là 6 ký tự số
-
mail.trap.username: Đây là username trong mailtrap khi bạn tạo mới 1 inbox
-
mail.trap.password: Đây là password trong mailtrap khi bạn tạo mới 1 inbox
8. Nội dung script file:
Tôi có file "otp.html", tôi khai báo đường dẫn cho script file:
Đường dẫn script file thì không phải cố định, tuỳ theo cấu trúc resources trên máy tính các bạn
9. Tạo phương thức tạo Otp code tự động:
Trong class "IOtpService", tôi khai báo phương thức "generateOtp()" - "getOtpExpiredAt()" - "checkOtp()":
Trong class "OtpService", tôi lấy ra giá trị thuộc tính "otp.max.length" tôi đã khai báo trong application file
Tạo phương thức "generateOtp()":
Tạo phương thức "getOtpExpiredAt()":
Tạo phương thức "checkOtp()":
10. Cấu hình gửi mail với MailTrap:
Để hiểu thêm về MailTrap, xem tại đây: https://help.mailtrap.io/article/40-faq#:~:text=Mailtrap is a fake SMTP,or flooding your own inboxes.
Sau khi chuẩn bị các bước trên, tiếp theo tôi hướng dẫn cấu hình để gửi mail với MailTrap:
Bước 1: Truy cập đường dẫn: https://mailtrap.io/
Bước 2: Tại trang chủ MailTrap -> đăng ký một tài khoản MailTrap, click button "Sign Up":
Bước 3: Các bạn chọn loại đăng ký, ở đây tôi chọn "Use Google account":
Bước 4: Sau khi tạo tài khoản thành công -> sẽ được điều hướng về trang dashboard của MailTrap, tại dashboard mục "Home" -> click button "Setup Inbox":
Bước 5: Sau khi tạo xong "Inbox" -> tại mục "Sanbox > Inboxes", tại tab "SMTP Settings" click "Show Credentials":
Trong phần credentials chứa thông tin port - username - password nên các bạn cần giữ kỹ thông tin này
Tiếp theo, tôi cấu hình cho phần gửi mail Otp code:
Đầu tiên, tôi cần thêm 1 dependency "javax.mail" trong file "pom.xml":
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.5.0-b01</version>
</dependency>
Nội dung file pom:
Tôi khai báo thêm 2 thuộc tính là "mail.trap.username" và "mail.trap.password" trong application.yml:
Usename và password các bạn sẽ thấy trong mục "Show Credentials" trong dashboard Mailtrap
Tôi khai báo phương thức "sendOtp" trong class "IOtpService":
Trong class "OtpService" lấy ra giá trị các thuộc tính username - password:
Phương thức "sendOtp" trong class "OtpService":
Tôi cần cập nhật lại code cho phương thức "checkInfoUserLogin" trong "OtpController", sau khi xác thực user có trong hệ thống -> generate new otp and gửi email đến user:
Sau khi gửi email thành công -> redirect -> otp page
Cập nhật lại phương thức "requestData()" trong script file:
Phương thức load otp page trong OtpController:
Tôi restart lại project và kiểm tra kịch bản user đăng nhập với tài khoản đúng -> otp được generate -> gửi mail với otp code đến user
=> Load thành công otp page
Kiểm tra database:
=> Thông tin otp được lưu thành công
Kiểm tra email gửi đến user, tôi vào trang dashboard của MailTrap. mục "Inbox":
=> Mail được gửi thành công
Tiếp theo, tôi cần xử lý tại FE sau khi nhập xong otp -> tự động call api đến BE để xác thực OTP và nếu xác thực thành công -> chuyển đến dashboard page
Tại page "otp.html" tôi cập nhật lại 1 vài thứ:
Template tôi sử dụng được thiết kế đơn giản nên tương ứng cho mỗi field là 1 thẻ "<input />" nên để bắt sự kiện sau khi user nhập full otp tôi thêm sự kiên "onchange" trong mỗi fields vá gọi đến phương thức "checkOtpCode()" trong script file. Nên để nhanh các bạn chỉ cần sửa 1 field và clone ra
Nội dung phương thức "checkOtpCode" trong UserController:
Nội dung phương thức "checkOtpCode" trong script file:
Nội dung phương thức "resendOtpCode" trong UserController:
Nội dung phương thức "resendOtpCode" trong script file:
Nội dung phương thức "getDashBoardPage" trong UserController:
Tôi restart lại project và kiểm tra kịch bản user đăng nhập với tài khoản xác thực thành công -> otp generated -> gửi mail otp và tôi nhập otp để kiểm tra:
=> Load dashboard page thành công
Tiếp theo, kiểm tra với kịch bản otp expired:
Kiểm tra với kịch bản resend otp:
Thêm sự kiện onclick trong button "Resend" trong otp page:
OTP đầu tiên:
Sau khi resend OTP:
Nếu bạn nào muốn thông qua MailTrap gửi mail đến email thực sự thì có thể bỏ ra "9.99$" mua gói 1 tháng để kiểm tra, tôi đã mua gói này và kiểm tra để thấy email người nhận OTP là gmail của tôi có nhận được không:
Trước tiên, sau khi nâng cấp MailTrap, tại dashboard MailTrap cần thiết lập lại tại mục "Auto Forward", tại đây tôi thiết lập mục Email là email domain gmail của tôi, sau khi add email của tôi xong -> tôi restart lại project và thử đăng nhập để xem OTP có được forward về gmail của tôi không:
Kiểm tra gmail:
=> Đã forward thành công và mail gửi đến sẽ nằm trong mục mail rác, để thiết lập nâng cao hơn, các bạn có thể add domain tại dashboard MailTrap
Cuối cùng, bài viết này không nhằm mục đích quảng cáo cho MailTrap, tôi thấy MailTrap này khá hay nên tôi muốn thử nghiệm và chia sẻ đến các bạn.
Ngoài ra, bởi vì các bạn đã biết thông thường gửi mail chúng ta hay sử dụng SMTP gmail nhưng hiện tại từ ngày 30-05-2022 gmail đã disable tính năng "less secure" trong mục "Security" mà trước đó để có thể gửi mail dùng SMTP gmail chúng ta cần tính năng "less secure" để passed
Xem thêm thông tin về vấn đề này tại đây:
Còn đây là cách để các bạn vẫn có thể sử dụng SMTP gmail để gửi mail mà không cần "less secure":