Kiểm soát truy cập dựa trên vai trò là gì

Kiểm soát truy cập dựa trên vai trò (RBAC) là một cách tiếp cận phổ biến để quản lý quyền truy cập của người dùng vào tài nguyên hoặc hoạt động. Quyền chỉ định chính xác tài nguyên và hành động nào có thể được truy cập. Nguyên tắc cơ bản là: thay vì quản lý riêng biệt các quyền của từng người dùng, các quyền được cấp cho các vai trò, sau đó được gán cho người dùng, hoặc tốt hơn - các nhóm người dùng.

Quyền gói vai trò

Quản lý quyền cho mỗi người dùng có thể là một công việc tẻ nhạt khi có nhiều người dùng tham gia. Khi người dùng được thêm vào hệ thống, việc duy trì các quyền của người dùng trở nên khó khăn hơn và dễ xảy ra lỗi hơn. Việc phân quyền không chính xác có thể chặn quyền truy cập của người dùng vào các hệ thống được yêu cầu, hoặc tệ hơn - cho phép người dùng trái phép truy cập vào các khu vực hạn chế hoặc thực hiện các hoạt động rủi ro.

Trong bài đăng này, tôi sẽ giới thiệu kinh nghiệm của tôi về cách kiểm soát quyền truy cập vào các ứng dụng RESTful một cách thanh lịch. Có nhiều mô hình kiểm soát truy cập khác nhau, chẳng hạn như Kiểm soát truy cập dựa trên vai trò (RBAC) và Kiểm soát truy cập tùy ý (DAC). Trong khi các nguyên tắc được giải thích trong tài liệu có thể áp dụng cho nhiều mô hình khác nhau, tôi đã chọn RBAC làm tài liệu tham khảo vì nó được chấp nhận rộng rãi và rất trực quan.

Một chút về vai trò

Kiểm soát truy cập dựa trên vai trò là một cách tiếp cận phổ biến để quản lý quyền truy cập của người dùng vào tài nguyên hoặc hoạt động. Quyền chỉ định chính xác tài nguyên và hành động nào có thể được truy cập. Nguyên tắc cơ bản là: thay vì quản lý riêng biệt các quyền của từng người dùng, các quyền được cấp cho các vai trò, sau đó được gán cho người dùng, hoặc tốt hơn - các nhóm người dùng.

Quyền gói vai trò

Quản lý quyền cho mỗi người dùng có thể là một công việc tẻ nhạt khi có nhiều người dùng tham gia. Khi người dùng được thêm vào hệ thống, việc duy trì các quyền của người dùng trở nên khó khăn hơn và dễ xảy ra lỗi hơn. Việc phân quyền không chính xác có thể chặn quyền truy cập của người dùng vào các hệ thống được yêu cầu, hoặc tệ hơn - cho phép người dùng trái phép truy cập vào các khu vực hạn chế hoặc thực hiện các hoạt động rủi ro.

Việc xem xét hoạt động của người dùng thường chỉ mang lại một số hành động hạn chế mà người dùng thực hiện (ví dụ: đọc dữ liệu, gửi biểu mẫu). Xem xét kỹ hơn các hành động này của người dùng có thể thấy rằng một số hành động có xu hướng đi cùng nhau, có nghĩa là người dùng thực hiện hành động A thường cũng thực hiện hành động B. Ví dụ: đọc và cập nhật báo cáo hoặc xóa và thêm tài khoản. Sau đó, những thứ này có thể được gộp thành “vai trò”, chẳng hạn như “Người biên tập” hoặc “Quản trị viên tài khoản”. Lưu ý rằng các vai trò không nhất thiết phải liên quan đến chức danh công việc hoặc cơ cấu tổ chức, mà là phản ánh các hành động liên quan của người dùng theo một cách có ý nghĩa. Sau khi các vai trò được xác định và gán đúng cách cho từng người dùng, các quyền sau đó có thể được chỉ định cho các vai trò, thay vì người dùng. Quản lý quyền của một số lượng nhỏ vai trò là một nhiệm vụ dễ dàng hơn nhiều.

Như mọi khi, một minh họa sẽ đi một chặng đường dài:

Dưới đây là một nhóm người dùng và các quyền được chỉ định của họ, được liên kết trực tiếp mà không có vai trò:

Và đây, cùng một tập hợp người dùng và quyền , được tổ chức với các vai trò:

Vì vậy, bạn có thể thấy rõ ràng cách các vai trò làm cho việc quản lý quyền dễ dàng hơn rất nhiều!

Nhóm người dùng nhóm

Một phương pháp hay hơn nữa là gán vai trò cho các nhóm người dùng, thay vì người dùng cá nhân.

Khi xem xét các mẫu hành động của người dùng liên quan đến các vai trò ở trên, chúng tôi thường thấy rằng có rất nhiều điểm chung giữa những người dùng, tức là các nhóm người dùng có xu hướng “hành xử” giống nhau - thực hiện các hoạt động giống nhau trên các tài nguyên chung. Điều này cho phép chúng tôi tổ chức người dùng thành các nhóm, sau đó chỉ định vai trò cho một vài nhóm, thay vì nhiều người dùng. Theo các ví dụ trước, có khả năng xảy ra trường hợp tìm thấy một số người dùng yêu cầu vai trò "Quản trị viên tài khoản", vì vậy chúng tôi có thể tạo một nhóm có tên "Quản trị viên tài khoản", thêm người dùng vào nhóm này và chỉ định vai trò đó cho nhóm, thay vào đó của mỗi người dùng cá nhân.

Thực hiện các vai trò - Nên và Không nên

Không bao giờ kết hợp các hành động và chi tiết ủy quyền

Trong nhiều hệ thống, các nhà phát triển hạn chế quyền truy cập vào một hoạt động cụ thể bằng cách chỉ định quyền trực tiếp trên phương thức triển khai. Có, trong mã! Thông thường, kiểm tra vai trò được thêm vào phương thức bảo mật, thường bằng cách chú thích nó. Đây là một ví dụ từ mã dựa trên Spring Security:

@PreAuthorize("hasRole('Editor')")public void update_order(Order order);

Đây là một thực tế rất phổ biến được sử dụng trong các ngôn ngữ và khuôn khổ khác nhau. Mặc dù rất dễ thực hiện, nhưng thật không may, nó lại tạo ra một sự kết hợp không mong muốn giữa vai trò được yêu cầu và việc triển khai thực tế của hành động. Hãy tưởng tượng hàng chục phương thức được chú thích bằng tên vai trò được mã hóa cứng. Việc theo dõi các quyền hiệu quả của từng vai trò trở nên khó khăn đến mức bạn gần như chắc chắn có thể tin tưởng vào việc có tài liệu không chính xác hoặc lỗi thời, hoặc thậm chí tệ hơn - các quyền không được quản lý, không xác định nằm rải rác trong ứng dụng của bạn.

Từ quan điểm của khách hàng, kiểu kết hợp này khiến cho việc sửa đổi nhóm vai trò được nhà phát triển xác định trước hoặc quyền của họ là không thể, bởi vì việc thay đổi nó có nghĩa là mã sẽ phải được biên dịch và đóng gói mỗi lần (!) - có lẽ không phải trải nghiệm người dùng mà chúng ta nên hướng tới. 

Làm thế nào để tránh ghép nối?

Một cách tiếp cận tốt hơn trước tiên là trích xuất danh sách các hành động có thể xảy ra từ mã sẽ được xử lý bởi một cơ chế ủy quyền bên ngoài (giải thích bên dưới). Sau đó, chúng ta có thể làm cho mã không biết đến các vai trò hoặc bất kỳ chi tiết ủy quyền nào khác và chỉ cần hỏi xem người dùng hiện tại (tuy nhiên nó được truy xuất) có quyền cần thiết (bất cứ nơi nào nó được xác định) để thực thi phương thức cụ thể.

Điều này sẽ cho phép chúng tôi sử dụng chú thích chung, như chú thích sau:

@Securedpublic void update_order(Order order);

Các vai trò và quyền ánh xạ (tức là quyền thực hiện một hành động cụ thể) hiện có thể được thực hiện trong một tệp cấu hình, khách hàng có thể dễ dàng tùy chỉnh!

Ví dụ: hãy xem xét tệp role_config.yaml này:

order_manager:
  - 'create_order'
  - 'view_order'
  - 'delete_order'
  - 'update_order'
order_inspector: 
  - 'viewer_order'

Trình @securedbao bọc hiện có thể đánh giá xem người dùng hiện tại có được phép thực thi 'update_order' dựa trên tệp cấu hình nhất định hay không. Trong trường hợp này, điều đó có nghĩa là người dùng hiện tại phải được chỉ định vai trò “người quản lý đơn hàng”, vai trò này hiện vừa rõ ràng vừa có thể định cấu hình dễ dàng. Tuy nhiên, cơ chế ủy quyền bằng cách nào đó phải biết cách khớp từng quyền với một phương thức cụ thể trong mã và ai đó phải thực hiện một số công việc và ghi lại tất cả các phương thức có sẵn (ví dụ: create_order, view_order, v.v.). Điều này được giải quyết (gần như) một cách kỳ diệu dưới đây.

Mối quan tâm riêng biệt - Ủy quyền bên ngoài

Bây giờ mã triển khai phương thức không bao gồm chi tiết ủy quyền, toàn bộ logic ủy quyền có thể được chuyển sang một mô-đun độc lập, riêng biệt. Bằng cách sử dụng tiêu đề chung chung (ví dụ: chú thích “được bảo mật”), chúng tôi cho phép toàn bộ cơ chế ủy quyền được sửa đổi mà không ảnh hưởng đến mã của ứng dụng. Ví dụ: có thể thực hiện “bảo mật” như một kiểm tra vai trò, nhưng cũng có thể sử dụng Danh sách kiểm soát truy cập (ACL). Ví dụ: đánh giá xem người dùng hiện tại có được liệt kê trong danh sách ACL của đơn đặt hàng hay không. Một giải pháp khác có thể là sử dụng oauth, bằng cách hỏi bên thứ ba (ví dụ: Facebook) xem người dùng có được phép thực hiện hành động đó hay không.

REST là tốt nhất

Khai thác hành động - Ra khỏi hộp

REST chắc chắn là tốt hơn, hoặc ít nhất là dễ dàng nhất để phù hợp với mô hình này. Các hệ thống RESTful (được thiết kế đúng cách) đã hiển thị các tài nguyên và phương thức thông qua một API dựa trên HTTP tiêu chuẩn, các tài nguyên được xác định bởi các URI và các phương thức được mô hình hóa bởi các động từ HTTP (ví dụ: GET, PUT).

Ví dụ: OST http://www.domain.com/bookingssẽ tạo một đặt chỗ mới và GET http://www.domain.com/orders/12345sẽ trả lại thông tin chi tiết về đơn đặt hàng số 12345. Điều đó có nghĩa là việc trích xuất các hành động được thảo luận ở trên đã sẵn sàng ngay lập tức!

Yêu cầu cổng

Ngoài các hành động mô hình hóa gọn gàng, các dịch vụ REST thường là một nơi tốt trong luồng yêu cầu để đánh giá xác thực và ủy quyền, vì đây thường là điểm vào chính của hệ thống. Để cơ chế kiểm soát truy cập hoạt động hiệu quả, bạn nên chặn tất cả các tuyến đường khác đến hệ thống, chẳng hạn như truy cập trực tiếp vào kho dữ liệu hoặc bất kỳ cơ chế gọi từ xa nào trong mã. Một lợi thế lớn khác của kiến ​​trúc này là lọc phản hồi, trong trường hợp một số dữ liệu không được trả lại cho người dùng.

Yêu cầu cũng là công cụ kiểm soát truy cập

Dịch vụ REST xử lý các yêu cầu đến, có nghĩa là thông tin được tìm thấy trên các yêu cầu có thể được sử dụng để đưa ra các quyết định kiểm soát truy cập. Một số chi tiết hữu ích là:

  • Yêu cầu nguồn gốc - Cho phép chặn các yêu cầu được gửi từ các địa chỉ IP hoặc mạng con không xác định.
  • Tiêu đề - Nhiều chi tiết thú vị có thể được chuyển vào tiêu đề, chẳng hạn như thông tin đăng nhập của người dùng, mở đầu cho quá trình xác thực / ủy quyền toàn diện diễn ra.
  • Điểm cuối mục tiêu - Như được chỉ ra bởi URI của yêu cầu (ví dụ: 'bí mật' trong ' http://domain.com/secrets/ '). Quyền truy cập có thể bị hạn chế đối với chỉ một tập hợp con các điểm cuối ứng dụng, tùy thuộc vào các điều kiện khác. Ví dụ: trong khi điểm cuối 'phiên bản' được mở cho tất cả, điểm cuối 'bí mật' chỉ mở cho người dùng đã xác thực.
  • Phương thức đích - Được đại diện bởi động từ HTTP (ví dụ: DELETE), có nghĩa là có thể chuyển hoặc chặn các yêu cầu dựa trên phương thức được gọi.

Kết hợp tất cả lại với nhau - Sử dụng REST để kiểm soát truy cập

Bạn có nhớ tệp cấu hình vai trò quyền đơn giản ở trên không? Nó trông khá thanh lịch nhưng lại đòi hỏi một số công việc đằng sau hậu trường (không được hiển thị trong tài liệu này), chẳng hạn như lấy danh sách tất cả các phương thức mà người dùng có thể gọi và khớp từng quyền với một phương thức cụ thể với tên đó. Không vui.

Điều này hiện đã được giải quyết!

Tất cả các tài nguyên có sẵn được hiển thị thông qua REST URI, cùng với các động từ HTTP, có thể bao gồm tất cả các hành động có thể được thực hiện và cần được bảo mật. Trong ví dụ dưới đây, 3 vai trò được định cấu hình:

  • order_manager - có thể xem, tạo, cập nhật và xóa đơn đặt hàng
  • order_editor - có thể xem, tạo và cập nhật đơn đặt hàng, nhưng không xóa chúng
  • order_ins Inspector - chỉ có thể xem các đơn đặt hàng
order_manager:
  '/orders':
    - 'GET'
    - 'POST'
    - 'PUT'
    - 'DELETE'
order_editor:
  '/orders':
    - 'GET'
    - 'POST'
    - 'PUT'
order_inspector:
  '/orders':
    - 'GET'

Vì vậy, bây giờ chúng tôi biết các hệ thống RESTful là một sự phù hợp tự nhiên để kiểm soát truy cập. Bằng cách xử lý các yêu cầu đến, dịch vụ REST có thể truy xuất thông tin có giá trị có thể được chuyển giao cho một mô-đun riêng biệt để thực hiện xác thực và ủy quyền. Nếu người dùng được ủy quyền để thực hiện phương thức được yêu cầu trên tài nguyên đích, quá trình xử lý yêu cầu có thể tiếp tục. Nếu không, đây là nơi thích hợp để từ chối truy cập thêm trước khi đạt được bất kỳ mã ứng dụng nội bộ nào.

Trong bài đăng tiếp theo của tôi, tôi sẽ giải thích cách chúng tôi triển khai mô hình RBAC này trong Cloudify, vì vậy hãy kiểm tra lại sớm.

16 hữu ích 0 bình luận 70k xem chia sẻ