Thiết kế hệ thống phân quyền cho ứng dụng đặt đồ ăn

Hệ thống phân quyền trong các ứng dụng quản lý nghiệp vụ như hệ thống đặt đồ ăn đòi hỏi sự linh hoạt cao, khả năng kiểm soát chi tiết theo chức năng và dễ tích hợp vào luồng xử lý hiện có. Bài viết này trình bày một kiến trúc phân quyền dựa trên mô hình RBAC (Role-Based Access Control) được áp dụng thực tế trong nhiều dự án thương mại điện tử và nền tảng giao dịch thực phẩm tại Đài Loan và Bắc Kinh.

Cấu trúc cơ sở dữ liệu cốt lõi

Hệ thống sử dụng năm bảng chính để biểu diễn mối quan hệ giữa người dùng, vai trò, module chức năng và quyền thao tác:

  • AdminUser: Lưu thông tin quản trị viên — trường RoleCode liên kết với bảng vai trò; cột IsSuperAdmin kiểu boolean giúp loại bỏ hoàn toàn kiểm tra phân quyền đối với tài khoản cấp cao nhất.
  • SystemRole: Định nghĩa các vai trò (ví dụ: Quản lý kho, Nhân viên chăm sóc khách hàng, Giám sát vận hành).
  • FeatureModule: Mô tả các nhóm chức năng hệ thống — mỗi bản ghi đại diện một module như Quản lý đơn hàng, Quản lý nhà hàng hoặc Báo cáo doanh thu. Trường ParentId hỗ trợ phân cấp hai mức (module cha – module con), còn RouteKey dùng để ánh xạ tới URL hoặc tên trang web cụ thể (ví dụ: ORD-01, REST-MNG-02).
  • OperationType: Liệt kê tất cả hành động có thể thực hiện trên một module — gồm Xem, Tạo mới, Cập nhật, Xóa, Xuất dữ liệu, Gán quyền… Mỗi hành động được gán một giá trị số dạng lũy thừa của 2 (1, 2, 4, 8, 16, 32...) nhằm tối ưu hóa phép kiểm tra bằng toán tử bitwise.
  • RoleFeatureAccess: Bảng trung gian lưu tổ hợp vai trò – module – tập quyền. Trường TotalPermissionMask là tổng bit-wise của tất cả hành động được cấp phép cho vai trò đó trên module tương ứng.

Cách thức xác thực quyền trong mã nguồn

Thay vì lặp lại logic kiểm tra ở từng phương thức xử lý yêu cầu, hệ thống triển khai một lớp tiện ích PermissionValidator với phương thức tĩnh HasAccess:

public static bool HasAccess(string currentRoute, OperationAction action)
{
    var currentUser = SessionContext.GetCurrentUser();
    if (currentUser?.IsSuperAdmin == true) return true;

    var rolePermissions = CacheService.GetCachedList<RoleFeatureAccess>(
        $"role_permissions_{currentUser.RoleCode}"
    );

    var targetModule = rolePermissions
        .FirstOrDefault(x => x.RouteKey.Equals(currentRoute, StringComparison.OrdinalIgnoreCase));

    if (targetModule == null) return false;

    int requiredBit = (int)Math.Pow(2, (int)action);
    return (targetModule.TotalPermissionMask & requiredBit) == requiredBit;
}

Ví dụ sử dụng trong controller xử lý yêu cầu cập nhật đơn hàng:

public ActionResult UpdateOrder(int id, OrderUpdateModel model)
{
    if (!PermissionValidator.HasAccess("ORD-01", OperationAction.Update))
    {
        return Json(new { success = false, message = "Bạn không có quyền chỉnh sửa đơn hàng." });
    }

    var result = _orderService.Update(id, model);
    return Json(new { success = result });
}

Ưu điểm thiết kế

  • Khả năng mở rộng cao: Việc thêm hành động mới chỉ cần chèn bản ghi vào OperationType và cập nhật TotalPermissionMask trong RoleFeatureAccess — không cần thay đổi logic nghiệp vụ.
  • Tối ưu hiệu năng: Toán tử bitwise giúp kiểm tra quyền chỉ trong O(1), tránh vòng lặp hoặc truy vấn CSDL mỗi lần gọi hàm.
  • Dễ bảo trì: Toàn bộ quy tắc phân quyền tập trung ở tầng service, không rải rác trong UI hay business logic.
  • Hỗ trợ cấu hình động: Giao diện quản trị cho phép admin điều chỉnh quyền theo vai trò mà không cần deploy lại hệ thống.

Mô hình tích hợp với hệ thống hiện hữu

Để giảm thiểu việc sao chép code kiểm tra quyền, hệ thống áp dụng kỹ thuật attribute-based authorization kết hợp với middleware tùy chỉnh. Một attribute như [RequirePermission("ORD-01", OperationAction.Delete)] có thể được gắn lên action method, sau đó tự động kích hoạt kiểm tra trước khi thực thi nghiệp vụ — đảm bảo tính nhất quán và loại bỏ lỗi do quên kiểm tra.

Thẻ: rbac asp.net csharp permissions web-security

Đăng vào ngày 27 tháng 6 lúc 10:05