4. Authorization Flow
Hãy đi sâu vào Authorization Flow trong Spring Security. Tôi sẽ giải thích về AccessDecisionManager
và Voter
trong việc ra quyết định phân quyền, cùng với cách sử dụng Expression-based Authorization (như @PreAuthorize
và hasRole
).
1. AccessDecisionManager và Voter trong việc ra quyết định phân quyền
a. AccessDecisionManager
Định nghĩa:
AccessDecisionManager
là một giao diện trong Spring Security, chịu trách nhiệm quyết định xem một người dùng có được phép truy cập tài nguyên hay không (authorization).Nó nhận thông tin từ
Authentication
(danh tính người dùng),ConfigAttribute
(quy tắc bảo mật, ví dụ: "ROLE_ADMIN"), và đối tượng tài nguyên (secure object) để đưa ra quyết định.
Vai trò:
Là "trọng tài" trong luồng phân quyền, tổng hợp ý kiến từ các
Voter
để ra phán quyết cuối cùng.
Các triển khai mặc định:
AffirmativeBased
(Mặc định):Chỉ cần một Voter đồng ý (vote "ACCESS_GRANTED") là cho phép truy cập.
ConsensusBased
:Quyết định dựa trên đa số phiếu từ các Voter.
UnanimousBased
:Yêu cầu tất cả Voter đồng ý thì mới cho phép.
Ví dụ cấu hình:
b. Voter
Định nghĩa:
AccessDecisionVoter
là các thành phần nhỏ hơn trongAccessDecisionManager
, mỗi Voter đưa ra ý kiến (vote) về việc có cho phép truy cập hay không.Kết quả vote có thể là:
ACCESS_GRANTED
: Đồng ý.ACCESS_DENIED
: Từ chối.ACCESS_ABSTAIN
: Không ý kiến (bỏ qua).
Các Voter phổ biến:
RoleVoter
:Kiểm tra vai trò của người dùng (dựa trên
GrantedAuthority
).Nếu tài nguyên yêu cầu "ROLE_ADMIN" và người dùng có "ROLE_ADMIN", vote
ACCESS_GRANTED
.
WebExpressionVoter
:Đánh giá các biểu thức SpEL (Spring Expression Language) như
hasRole()
,permitAll()
, từ cấu hìnhauthorizeRequests
.
AuthenticatedVoter
:Kiểm tra trạng thái xác thực (IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_ANONYMOUSLY).
Ví dụ custom Voter:
Đăng ký Voter này vào
AccessDecisionManager
để kiểm tra quyền tùy chỉnh.
Luồng hoạt động:
FilterSecurityInterceptor
(filter cuối trong Filter Chain) gọiAccessDecisionManager
.AccessDecisionManager
gửiAuthentication
, tài nguyên, vàConfigAttribute
đến từngVoter
.Các Voter vote, và
AccessDecisionManager
tổng hợp kết quả theo chiến lược (Affirmative, Consensus, Unanimous).Nếu được phép, request tiếp tục; nếu không, ném
AccessDeniedException
.
2. Expression-based Authorization (@PreAuthorize, hasRole)
a. Tổng quan
Expression-based Authorization:
Spring Security cho phép định nghĩa quyền truy cập bằng các biểu thức SpEL (Spring Expression Language), thay vì chỉ dựa trên vai trò cố định.
Được áp dụng trong cấu hình
HttpSecurity
hoặc annotation như@PreAuthorize
,@PostAuthorize
.
Ưu điểm:
Linh hoạt, có thể kiểm tra quyền theo ngữ cảnh (context), thuộc tính người dùng, hoặc logic phức tạp.
b. Các biểu thức phổ biến
hasRole('ROLE_NAME')
:Kiểm tra xem người dùng có vai trò cụ thể không.
hasAuthority('AUTHORITY')
:Tương tự
hasRole
, nhưng không thêm tiền tố "ROLE_".
hasAnyRole('ROLE1', 'ROLE2')
:Kiểm tra nếu có ít nhất một trong các vai trò.
permitAll()
: Cho phép tất cả.denyAll()
: Từ chối tất cả.isAuthenticated()
: Yêu cầu đã xác thực.authentication
: Truy cập đối tượngAuthentication
.
c. Sử dụng trong HttpSecurity
Ví dụ:
WebExpressionVoter
sẽ đánh giá các biểu thức này trong Filter Chain.
d. Sử dụng annotation (@PreAuthorize, @PostAuthorize)
Cần bật Method Security:
@PreAuthorize
:Kiểm tra quyền trước khi thực thi phương thức.
Ví dụ:
@PostAuthorize
:Kiểm tra quyền sau khi phương thức chạy, dựa trên kết quả trả về.
Ví dụ:
Kết hợp với tham số:
Dùng
#param
để truy cập tham số phương thức trong biểu thức.
e. Cách hoạt động
Khi dùng
@PreAuthorize
hoặc@PostAuthorize
, Spring Security tạo một proxy (AOP) quanh phương thức.MethodSecurityInterceptor
gọiAccessDecisionManager
để đánh giá biểu thức SpEL, với sự hỗ trợ củaWebExpressionVoter
.
Tóm tắt
AccessDecisionManager và Voter:
AccessDecisionManager
tổng hợp ý kiến từ cácVoter
để quyết định phân quyền.Voter
(nhưRoleVoter
,WebExpressionVoter
) kiểm tra quyền dựa trên vai trò hoặc biểu thức.
Expression-based Authorization:
Dùng SpEL trong
HttpSecurity
(hasRole
) hoặc annotation (@PreAuthorize
) để định nghĩa quyền linh hoạt.
Last updated