Method-level security bảo vệ từng method bằng annotation thay vì chỉ bảo vệ ở URL level.
Bật method security (Spring Security 6):
@Configuration
@EnableMethodSecurity // thay @EnableGlobalMethodSecurity đã deprecated
class SecurityConfig { ... }@PreAuthorize — kiểm tra trước khi method chạy:
@Service
class OrderService {
@PreAuthorize("hasRole('ADMIN')")
void deleteOrder(Long id) { ... } // chỉ ADMIN
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
List<Order> getAllOrders() { ... } // ADMIN hoặc MANAGER
// SpEL: kiểm tra ownership — chỉ chủ order mới xem được
@PreAuthorize("#orderId == authentication.principal.id or hasRole('ADMIN')")
Order getOrder(Long orderId) { ... }
// Kiểm tra method argument
@PreAuthorize("#user.username == authentication.name")
void updateProfile(User user) { ... }
}@PostAuthorize — kiểm tra sau khi method chạy (dùng khi cần check return value):
@PostAuthorize("returnObject.owner == authentication.name")
Document getDocument(Long id) { ... } // method chạy, rồi check owner@Secured — đơn giản hơn, không có SpEL:
@Secured("ROLE_ADMIN")
void adminOnlyAction() { ... }Lưu ý:
- @PreAuthorize dùng SpEL → linh hoạt nhất, recommended.
- Hoạt động qua AOP proxy → self-invocation không được bảo vệ.
- @EnableMethodSecurity thay cho @EnableGlobalMethodSecurity từ Spring Security 6.
Method-level security protects individual methods with annotations rather than only at the URL level.
Enable method security (Spring Security 6):
@Configuration
@EnableMethodSecurity // replaces deprecated @EnableGlobalMethodSecurity
class SecurityConfig { ... }@PreAuthorize — checks before the method runs:
@Service
class OrderService {
@PreAuthorize("hasRole('ADMIN')")
void deleteOrder(Long id) { ... } // ADMIN only
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
List<Order> getAllOrders() { ... } // ADMIN or MANAGER
// SpEL: ownership check — only the order's owner can view
@PreAuthorize("#orderId == authentication.principal.id or hasRole('ADMIN')")
Order getOrder(Long orderId) { ... }
// Check method argument
@PreAuthorize("#user.username == authentication.name")
void updateProfile(User user) { ... }
}@PostAuthorize — checks after the method runs (use when you need to check the return value):
@PostAuthorize("returnObject.owner == authentication.name")
Document getDocument(Long id) { ... } // method runs, then checks owner@Secured — simpler, no SpEL support:
@Secured("ROLE_ADMIN")
void adminOnlyAction() { ... }Notes:
- @PreAuthorize uses SpEL → most flexible, recommended.
- Works through AOP proxy → self-invocation is not protected.
- @EnableMethodSecurity replaces @EnableGlobalMethodSecurity since Spring Security 6.