1. Giới thiệu
Tiếp theo phần 1 trong chuỗi bài viết về phát triển REST API, phần này sẽ hướng dẫn bạn cách tích hợp Spring Security vào dự án của bạn. Chúng ta sẽ cùng tìm hiểu cách bảo mật ứng dụng với JWT và Oauth2. Bạn có thể đọc lại phần 1 tại đây: Phần 1 - Xây dựng project REST API cơ bản.
2. Thêm Dependency vào Dự Án
Để bắt đầu, chúng ta cần thêm dependency cho Spring Security vào dự án của bạn. Nếu bạn đang sử dụng IntelliJ Ultimate, bạn có thể mở file pom.xml
, chọn Edit Starters và thêm Spring Security.
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
3. Luồng Xử Lý Bên Trong Spring Security
Trước khi tích hợp bảo mật cho dự án, mình sẽ giải thích về luồng xử lý của Spring Security. Hãy mở từng file mà mình đề cập để có thể hiểu rõ nhất về flow này.
Bước 1: Bộ lọc (Filters) của Spring Security
Khi người dùng gửi thông tin đăng nhập đến backend, Spring Boot sẽ gọi đến class AuthenticationFilter.java trong package org.springframework.security.web.authentication và thực hiện method doFilterInternal.
Bước 2: Xác thực (Authentication)
Trong method doFilterInternal, sẽ gọi method attemptAuthentication và sau đó là method authenticationManager.authenticate(authentication).
Bước 3: Quản lý xác thực (Authentication Manager)
AuthenticationManager có nhiều class triển khai khác nhau, trong đó có ProviderManager.java. Phương thức này sử dụng vòng lặp để gọi đến tất cả các provider bởi vì AuthenticationManager chịu trách nhiệm quản lý nhiều provider khác nhau như OAuth2AuthenticationProvider hay DaoAuthenticationProvider.
Bước 4: Provider Xác Thực (AuthenticationProvider)
Bên trong method authenticate, gọi đến interface AuthenticationProvider và tiếp tục gọi đến class AbstractUserDetailsAuthenticationProvider. Từ đây, nó sẽ gọi method retrieveUser(...), trỏ đến method trong class DaoAuthenticationProvider.java, cùng lúc gọi đến method loadUserByUsername(username).
Bước 5: Dịch Vụ Thông Tin Người Dùng (UserDetailService)
Tại đây, Spring Security sẽ gọi đến class InMemoryUserDetailsManager và lấy thông tin người dùng dựa trên username đã nhập.
Bước 6: Mã hóa mật khẩu (PasswordEncoder)
Sau khi hoàn tất bước 4, logical flow tiếp theo là kiểm tra xem mật khẩu người dùng nhập vào (sau khi mã hóa) có khớp với mật khẩu đã lưu không thông qua class DaoAuthenticationProvider.
Bước 7, 8, 9: Hoàn tất Kiểm Tra Bảo Mật
Cuối cùng, sau khi hoàn thành tất cả các bước kiểm tra, dữ liệu sẽ được trả về và thêm thông tin người dùng vào SecurityContextHolder thông qua SecurityContextHolder.getContext().setAuthentication(auth);
.
4. Kết Luận
Bài viết này cung cấp nhiều kiến thức quan trọng. Trong phần tiếp theo, mình sẽ triển khai bảo mật cho dự án. Hãy đọc kỹ để hiểu rõ lý thuyết này vì nó rất quan trọng cho việc thực hiện mã sau này. Xin cảm ơn các bạn đã theo dõi!
source: viblo