Hierarchical RBAC: Khi Cấu Trúc Phân Quyền "Tiến Hóa" Để Cứu Lấy Hệ Thống Khỏi Cơn Ác Mộng Cấu Hình
Chào anh em. Ở bài trước, mình đã nhắc đến một "nỗi đau" chí mạng khi hệ thống to lên: Sự bùng nổ của Role (Role Explosion).
Khi công ty chỉ có 5-10 vị trí, RBAC phẳng (Plat RBAC) với 5 cái bảng hoạt động cực mượt. Nhưng hãy tưởng tượng bạn đang build hẹ thống cho một tập đoàn. Họ có Thực tập sinh, Nhân viên chính thức, Trưởng nhóm, Trưởng phòng, Giám đốc.
Theo logic thông thường, một Trưởng nhóm sẽ phải làm được mọi thứ mà Nhân viên làm được, cộng thêm quyền duyệt báo cáo. Nếu dùng RBAC phẳng, bạn sẽ phải gán lại toàn bộ permission của Nhân viên cho role Trưởng nhóm. hệ quả là: khi có một tính năng mới (ví dụ: quyền xem menu ăn trưa), bạn phải đi tick chọn permission đó cho TẤT CẢ các role từ dưới lên trên. Sai sót là điều chắc chắc xảy ra!
Đó là lúc Hierarchical RBAC (HRBAC - Phân quyền theo vai trò kế thừa) xuất hiện như một đấng cứu thế.
1. Bản Chất Của Hierarchical RBAC Là Gì?
Lấy cảm hứng từ Lập Trình Hướng Đối Tượng (OOP), HRBAC cho phép các Role kế thừa (inherit) lẫn nhau.
Thay vì gán lại từ đầu, bạn thiết lập: Role Trưởng nhóm kế thừa Role Nhân viên.
Hệ thống sẽ tự hiểu: Trưởng nhóm sẽ sở hữu toàn bộ Permission của Trưởng nhóm + toàn bộ Permisson của Nhân viên.
Lợi ích khổng lồ:
- Giảm thiểu sai sót: Cấp thêm 1 quyền cơ bản cho
Nhân viên, lập tức toàn bộ cấp quản lý phía trên tự động có quyền đó. Không cần tick tay hàng loạt - Database gọn gàng: Bảng
role_permissionsgiảm được hàng nghìn dòng dữ liệu thừa. - Mô phỏng chuẩn cấu trúc doanh nghiệp: Sơ đồ tổ chức (Org Chart) công ty thế nào, cấu trúc Role của bạn ánh xạ y chang như vậy.
2. Thiết Kế Database Cho HRBAC: Dễ Mà Khó
Để cấu hình kế thừa, cấu trúc 5 bảng truyền thống cần một chút "ma thuật". Có 2 cách phổ biến anh em hay làm:
Cách 1: Thêm cột parent_id vào bảng roles (Adjacency List - Dễ làm nhất)
- Bảng
roles:id,name,parent_id - Ví dụ: Role
Nhân viên(id: 1, parent_id: null). RoleTrưởng nhóm(id: 2, parent_id: 1). - Ưu điểm: Cực kỳ dễ hiểu, thêm sửa xóa Role trên UI rất nhàn.
Cách 2: Dùng bảng trung gian role_hierarchy (Linh hoạt nhất)
- Đôi khi một Role có thể kế thừa từ NHIỀU Role khác (Đa kế thừa). Cột
parent_idsẽ bất lực. - Lúc này ta tạo bảng
role_hierarchygồm 2 cột:parent_role_idvàchild_role_id.
3. Những "Cái Bẫy" Của Kế Thừa Mà Dev Mới Thường Rơi Vào
Mang tiếng là bài chia sẻ kinh nghiệm 20 năm, mình sẽ không dừng lại ở lý thuyết suông. Dưới đây là những "hố bom" kiến trúc mà HRBAC mang lại nếu bạn code không khéo:
Bẫy #1: Kế Thừa Vòng Tròn (Circular Inheritance) - Treo Luôn Cả Server
Hãy tưởng tượng Admin lỡ tay cấu hình thế này:
- Role A kế thừa Role B.
- Role B kế thừa Role C.
- Role C lại... kế thừa Role A.
Bùm! Khi user login, code của bạn sẽ chạy một vòng lặp vô hạn (Infinite Loop) để quét tìm các Permission, RAM tăng vọt và server crash.
- Kinh nghiệm: Trước khi Insert/Update quan hệ kế thừa vào Database, BẮT BUỘC phải viết một hàm đệ quy (hoặc dùng thuật toán duyệt đồ thị DAG) để check xem có bị lặp vòng không. Nếu có, văng lỗi ngay lập tức!
Bẫy #2: Hiệu Năng Truy Vấn (Query Performance) Bị Bóp Nghẹt
Nếu sơ đồ Role của bạn sâu 5 cấp bậc, khi check quyền của cấp cao nhất, bạn sẽ phải join bảng hoặc đệ quy 5 lần xuống DB. Trong SQL, query dạng cây (Tree) cực kỳ tốn tài nguyên.
Kinh nghiệm: Sử dụng Recursive CTE (Common Table Expressions) nếu dùng PostgreSQL/MySQL 8.0+ để lấy toàn bộ cây phân quyền trong 1 câu query.
Tuyệt chiêu thực chiến: Đừng bao giờ đệ quy lấy quyền ở mỗi request! Khi User được gán Role hoặc Role bị thay đổi permission, hãy tính toán (Flatten) ngay lập tức toàn bộ permission mà User đó có (kể cả từ kế thừa), rồi nhét thành một mảng phẳng vào Redis hoặc JWT. Lúc check quyền, chỉ việc đọc array.includes('permission') - tốc độ O(1) chớp mắt.
Bẫy #3: Lạm Dụng Kế Thừa (Over-engineering)
Nhiều anh em học được HRBAC xong thì dự án nào cũng lôi ra dùng, kể cả web bán hàng nhỏ xíu chỉ có Admin và Customer. Cấu trúc cây làm việc code logic check quyền trở nên cồng kềnh không cần thiết.
Kinh nghiệm: Chỉ xài dao mổ trâu khi gặp trâu. Nếu hệ thống dưới 10 roles và nghiệp vụ không đổi liên tục, RBAC phẳng vẫn là chân ái. Đừng tự làm khổ mình.
Tóm Lại
Hierarchical RBAC là bước tiến hóa bắt buộc khi bạn làm việc với phần mềm doanh nghiệp (Enterprise Software), ERP hay SaaS quy mô lớn. Nó giữ cho hệ thống phân quyền của bạn sạch sẽ, logic và dễ bảo trì khi công ty scale up.
Nhưng nhớ kỹ câu thần chú: "Lưu trữ dạng cây, nhưng đọc ra phải dạng phẳng". Việc tối ưu Cache cho mô hình này quyết định 90% sự thành bại của hệ thống.
All rights reserved