Kiểm soát truy cập dựa trên vai trò và quyền


44

Tôi đang cố gắng hiểu sự đánh đổi vốn có giữa vai trò và quyền khi nói đến kiểm soát truy cập (ủy quyền).

Hãy bắt đầu với một thứ nhất định: trong hệ thống của chúng tôi, Quyền sẽ là đơn vị truy cập chi tiết (" Chỉnh sửa tài nguyên X ", " Truy cập trang bảng điều khiển ", v.v.). Một Vai trò sẽ là một bộ sưu tập các 1+ Permissions. Một người dùng có thể có hơn 1 vai trò. Tất cả các mối quan hệ này (Người dùng, Vai trò, Quyền) đều được lưu trữ trong cơ sở dữ liệu và có thể được thay đổi nhanh chóng và khi cần.

Mối quan tâm của tôi:

(1) Điều gì là "xấu" về việc kiểm tra Vai trò kiểm soát truy cập? Thay vào đó, những lợi ích nào đạt được bằng cách kiểm tra các quyền? Nói cách khác, sự khác biệt giữa hai đoạn trích dưới đây:

if(SecurityUtils.hasRole(user)) {
    // Grant them access to a feature
}

// vs.
if(SecurityUtils.hasPermission(user)) {
    // Grant them access to a feature
}

Và:

(2) Trong kịch bản này, Roles thậm chí còn cung cấp giá trị hữu ích nào? Chúng ta không thể chỉ định 1+ Quyền cho Người dùng trực tiếp sao? Có gì cụ thể giá trị trừu tượng làm Vai trò cung cấp (ví dụ thể có người cho cụ thể)?


2
Một vài điểm: (1) một người dùng có thể có nhiều vai trò, (2) bạn có thể muốn xem xét ACL (Danh sách điều khiển truy cập), vd. bạn có thể muốn cấp "Truy cập trang bảng điều khiển" cho một tập hợp con của các trang bảng điều khiển (nếu có một số).
Matthieu M.

Câu trả lời:


62

(1) Điều gì là "xấu" về việc kiểm tra Vai trò kiểm soát truy cập? Thay vào đó, những lợi ích nào đạt được bằng cách kiểm tra các quyền?

Tại thời điểm kiểm tra, mã cuộc gọi chỉ cần biết "người dùng X có được phép thực hiện hành động Y không?" .
Mã cuộc gọi không quan tâm và không nên nhận thức được mối quan hệ giữa vai trò và quyền.

Lớp ủy quyền sau đó sẽ kiểm tra xem người dùng có quyền này hay không, thông thường bằng cách kiểm tra xem vai trò của người dùng có quyền này hay không. Điều này cho phép bạn thay đổi logic ủy quyền mà không cần cập nhật mã cuộc gọi.

Nếu bạn trực tiếp kiểm tra vai trò tại trang web cuộc gọi, bạn đang hoàn toàn hình thành vai trò relationships mối quan hệ cấp phép và đưa logic ủy quyền vào mã cuộc gọi, vi phạm phân tách mối quan tâm.

Nếu sau đó bạn quyết định vai trò foođó không được phép baz, bạn sẽ phải thay đổi mọi mã kiểm tra xem người dùng có phải là một foo.

(2) Trong kịch bản này, Roles thậm chí còn cung cấp giá trị hữu ích nào? Chúng ta không thể chỉ định 1+ Quyền cho Người dùng trực tiếp sao? Giá trị cụ thể của sự trừu tượng mà Roles đưa ra (ai đó có thể đưa ra ví dụ cụ thể)?

Vai trò đại diện cho một tập hợp các quyền được đặt tên.

Giả sử bạn đang thêm một tính năng mới cho phép người dùng chỉnh sửa một số cài đặt nhất định. Tính năng này chỉ có sẵn cho quản trị viên.

Nếu bạn đang lưu trữ quyền cho mỗi người dùng, bạn sẽ phải tìm tất cả người dùng trong cơ sở dữ liệu của mình mà bạn biết là quản trị viên (Nếu bạn không lưu trữ thông tin vai trò cho người dùng, làm sao bạn biết người dùng nào là quản trị viên?) Và nối thêm quyền này vào danh sách quyền của họ.

Nếu bạn sử dụng vai trò, bạn chỉ phải thêm quyền cho Administratorvai trò, điều này vừa dễ thực hiện hơn, vừa tiết kiệm không gian hơn và ít bị mắc lỗi hơn.


Ừm Lớp xác thực sẽ kiểm tra xem người dùng có phải là người tự xưng không; lớp kiểm tra chức năng / dữ liệu nào mà người dùng có thể truy cập là lớp ủy quyền
SJuan76

4
Điều này nên được đọc bắt buộc cho tất cả các lập trình viên. Xuất sắc.
Kosta Kontos

2
Đơn giản, súc tích, và đến mức - đánh bại cả một chương của một cuốn sách ở đâu đó. Cảm ơn.
Dan Nissenbaum

2
Nhận xét cho rõ ràng (và vui lòng sửa lại cho tôi nếu tôi nhầm): Có authorization layerkhả năng không có gì khác hơn là chỉ đơn giản là có định nghĩa của hàm (nghĩa là) user->hasPermission(SOME_PERMISSION)kiểm tra bên trong vai trò của người dùng trước và sau đó kiểm tra xem có bất kỳ vai trò nào bao gồm / loại trừ vai trò đã cho không sự cho phép Ví dụ: the calling codecó thể đang kiểm tra xem liệu một trang nhất định có hiển thị cho người dùng hay không và sẽ gọi user->hasPermission(VIEW_GIVEN_PAGE), và authorization layerbao gồm định nghĩa của hasPermissionhàm kiểm tra các vai trò như trên.
Dan Nissenbaum

1
@DanNissenbaum Vâng, có vẻ như bạn đã hiểu đúng, nó có thể đơn giản như việc kiểm tra xem vai trò của người dùng có được ủy quyền này hay không. Nó cũng có thể nhiều hơn thế. Ví dụ: có thể bạn có tùy chọn tạm thời đình chỉ người dùng và trong trường hợp đó hasPermissioncó thể kiểm tra usersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended. Vấn đề là tất cả được thực hiện ở một nơi chứ không phải trong mã tiêu dùng (gọi điện).
Rotem

18

Để trả lời câu hỏi đầu tiên của bạn, vấn đề lớn nhất khi kiểm tra xem người dùng có vai trò nào hơn là một quyền cụ thể, đó là quyền có thể được giữ bởi nhiều vai trò. Để làm ví dụ cho điều này, một nhà phát triển có thể có quyền truy cập để xem cổng thông tin của nhà phát triển trên mạng nội bộ của công ty, đây có lẽ cũng là một sự cho phép của người quản lý của họ. Nếu người dùng đang cố truy cập vào cổng thông tin của nhà phát triển, bạn sẽ có một kiểm tra tương tự như:

if(SecurityUtils.hasRole(developer)) {
    // Grant them access to a feature
} else if(SecurityUtils.hasRole(manager)) {
    // Grant them access to a feature
} else if...

(Một switchtuyên bố trong ngôn ngữ bạn chọn sẽ tốt hơn, nhưng vẫn không đặc biệt gọn gàng)

Quyền càng phổ biến hoặc được tổ chức rộng rãi, bạn càng cần kiểm tra nhiều vai trò người dùng hơn để đảm bảo rằng ai đó có thể truy cập vào một hệ thống nhất định. Điều này cũng sẽ dẫn đến một vấn đề là mỗi khi bạn sửa đổi quyền cho một vai trò, bạn sẽ cần sửa đổi kiểm tra để phản ánh điều này. Trong một hệ thống lớn, điều này sẽ trở nên rất khó sử dụng rất nhanh.

Nếu bạn chỉ cần kiểm tra xem người dùng có quyền cho phép họ truy cập vào cổng nhà phát triển hay không, thì họ không có vai trò gì, họ sẽ được cấp quyền truy cập.

Để trả lời câu hỏi thứ hai của bạn, lý do bạn có vai trò là vì chúng hoạt động dễ dàng sửa đổi và phân phối "gói" quyền. Nếu bạn có một hệ thống có hàng trăm vai trò và hàng ngàn quyền, việc thêm người dùng mới (ví dụ: người quản lý nhân sự mới) sẽ yêu cầu bạn thực hiện và cấp cho họ mọi quyền mà người quản lý nhân sự khác nắm giữ. Điều này không chỉ tẻ nhạt, mà còn dễ bị sai lầm nếu được thực hiện thủ công. So sánh điều này với việc chỉ cần thêm vai trò "người quản lý nhân sự" vào hồ sơ của người dùng, điều này sẽ cấp cho họ quyền truy cập giống như mọi người dùng khác có vai trò đó.

Bạn có thể lập luận rằng bạn có thể chỉ cần sao chép một người dùng hiện tại (nếu hệ thống của bạn hỗ trợ điều này), nhưng trong khi điều này cấp cho người dùng quyền chính xác tại thời điểm đó, thì việc cố gắng thêm hoặc xóa quyền cho tất cả người dùng trong tương lai có thể khó khăn. Một kịch bản ví dụ cho điều này là nếu có thể trong quá khứ, nhân viên nhân sự cũng chịu trách nhiệm về biên chế, nhưng sau đó, công ty đủ lớn để thuê nhân viên đặc biệt để xử lý bảng lương. Điều này có nghĩa là HR không còn cần phải truy cập vào hệ thống bảng lương, do đó có thể xóa quyền. Nếu bạn có 10 thành viên nhân sự khác nhau, bạn sẽ cần phải thực hiện thủ công và đảm bảo bạn xóa quyền chính xác dẫn đến khả năng xảy ra lỗi người dùng. Vấn đề khác với điều này là nó đơn giản là không có quy mô; khi bạn có được càng nhiều người dùng trong một vai trò nhất định, điều đó làm cho việc sửa đổi vai trò trở nên khó khăn hơn nhiều. So sánh điều này với việc sử dụng các vai trò, trong đó bạn chỉ cần sửa đổi vai trò bao quát trong câu hỏi để loại bỏ quyền, điều này sẽ được phản ánh bởi mọi người dùng giữ vai trò đó.


ví dụ tốt, cảm ơn!
thẳng thắn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.