Phân quyền trong Spring Boot thường được thực hiện thông qua Spring Security, một framework mạnh mẽ cho việc bảo mật ứng dụng. Dưới đây là hướng dẫn chi tiết về cách cấu hình và sử dụng phân quyền trong một ứng dụng Spring Boot.
Để bắt đầu, bạn cần thêm dependency của Spring Security vào dự án của mình. Nếu bạn đang sử dụng Maven, thêm đoạn sau vào file pom.xml
:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Nếu bạn sử dụng Gradle, thêm vào file build.gradle
:
implementation 'org.springframework.boot:spring-boot-starter-security'
Tạo một class cấu hình cho Spring Security. Class này sẽ mở rộng WebSecurityConfigurerAdapter
và ghi đè các phương thức cần thiết.
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() // Cho phép truy cập không cần xác thực .antMatchers("/admin/**").hasRole("ADMIN") // Chỉ cho phép người dùng có vai trò ADMIN .anyRequest().authenticated() // Tất cả các yêu cầu khác cần phải xác thực .and() .formLogin() // Sử dụng form đăng nhập .permitAll() .and() .logout() .permitAll(); } }
Bạn cần tạo người dùng và vai trò để phân quyền. Dưới đây là một ví dụ đơn giản về cách tạo một UserDetailsService
:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; @Service public class CustomUserDetailsService implements UserDetailsService { private Map<String, User> users = new HashMap<>(); @Autowired private PasswordEncoder passwordEncoder; public CustomUserDetailsService() { // Tạo một số người dùng giả lập users.put("admin", new User("admin", passwordEncoder.encode("admin123"), "ROLE_ADMIN")); users.put("user", new User("user", passwordEncoder.encode("user123"), "ROLE_USER")); } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = users.get(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.getAuthorities()); } }
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import java.util.Collection; import java.util.Collections; public class User { private String username; private String password; private String role; public User(String username, String password, String role) { this.username = username; this.password = password; this.role = role; } public String getUsername() { return username; } public String getPassword() { return password; } public Collection<? extends GrantedAuthority> getAuthorities() { return Collections.singletonList(new SimpleGrantedAuthority(role)); } }
Bạn có thể sử dụng các annotation như @PreAuthorize
hoặc @Secured
trên các phương thức trong controller để phân quyền chi tiết hơn.
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @GetMapping("/public") public String publicEndpoint() { return "Đây là trang công khai."; } @GetMapping("/admin") @PreAuthorize("hasRole('ADMIN')") public String adminEndpoint() { return "Chỉ dành cho quản trị viên."; } @GetMapping("/user") @PreAuthorize("hasRole('USER')") public String userEndpoint() { return "Chỉ dành cho người dùng."; } }
Để mã hóa mật khẩu, bạn cần thêm một bean cho PasswordEncoder
. Thêm vào class cấu hình của bạn:
import org.springframework.context.annotation.Bean; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
Bây giờ bạn có thể chạy ứng dụng và kiểm tra các điểm cuối (endpoint) đã được bảo mật. Bạn có thể sử dụng một công cụ như Postman để gửi yêu cầu đến các endpoint với thông tin đăng nhập khác nhau để xem phân quyền hoạt động như thế nào.
Phân quyền trong Spring Boot với Spring Security rất linh hoạt và mạnh mẽ. Bạn có thể dễ dàng cấu hình quyền truy cập cho từng endpoint, cũng như sử dụng annotation để kiểm soát quyền truy cập cho từng phương thức. Hãy chắc chắn rằng bạn đã cài đặt đúng các dependency và cấu hình để có được trải nghiệm tốt nhất với bảo mật trong ứng dụng của mình.