2009-10-10 35 views
25

Tôi đang tìm một số đầu vào về cách những người khác sẽ kiến ​​trúc sư này. Tôi sẽ cung cấp các khung nhìn dựa trên lớp (nhóm django).Lượt xem dựa trên vai trò Django?

Ví dụ: nhóm của người dùng sẽ xác định lượt xem/mẫu mà họ sẽ có quyền truy cập. Tôi đang nghĩ đến việc lưu trữ các đường dẫn để xem các hàm trong bảng để xác định thanh liên kết của người dùng sẽ bao gồm những gì. Thông số kỹ thuật bộ lọc cũng có thể được lưu trữ để xác định những hàng nào sẽ điền vào các mẫu này.

Ví dụ điển hình là đơn vị điều dưỡng tại bệnh viện. Y tá tại một đơn vị không cần phải nhìn toàn bộ bệnh nhân của bệnh viện. Họ chỉ cần nhìn thấy bệnh nhân của họ. Các bác sĩ trên cùng một đơn vị chỉ cần nhìn thấy những bệnh nhân đó, nhưng họ nên có quyền truy cập vào chức năng lớn hơn nhiều.

Điều này có được thực hiện thông qua một số ứng dụng của bên thứ ba không? Và làm cách nào bạn tiếp cận vấn đề này?

Cảm ơn, Pete

+1

Guys, hệ thống cho phép django không phù hợp với nhu cầu của tôi. Đó là lý do tại sao tôi yêu cầu trợ giúp về kiến ​​trúc: P – slypete

Trả lời

38

Django đã có một nhóm và cho phép hệ thống, mà có thể là đủ cho mục đích của bạn.

http://docs.djangoproject.com/en/dev/topics/auth/

Nói chung trong mã của bạn, bạn kiểm tra xem người dùng có được phép hay không. Người dùng có quyền của riêng mình và những người thuộc nhóm anh ấy. Bạn có thể quản lý điều này khá dễ dàng từ bảng điều khiển dành cho quản trị viên.

Có hai phần bạn cần xem xét.

  1. Kiểm tra xem người dùng yêu cầu trang có quyền làm như vậy không.
  2. Chỉ hiển thị liên kết cho người dùng nếu anh ta có sự cho phép.

Đối 1. Bạn có thể kiểm tra điều khoản trong một trang trí như vậy:

from django.contrib.auth.decorators import permission_required 

@permission_required('polls.can_vote') 
def some_view(request): 

Đối 2. quyền của người sử dụng hiện đang đăng nhập được lưu trữ trong các mẫu biến {{perms}}. Mã này kiểm tra sự cho phép tương tự như trên.

{% if perms.polls.can_vote %} 
    <a href="/vote">vote</a> 
{% endif %} 

Để tạo một danh sách liên kết, bạn có thể duyệt qua user.get_all_permissions() và lấy các liên kết (hoặc chức năng mà tạo ra các liên kết) từ một dict:

def more_elaborate_list_of_links_for_a_perm(user): 
    return ["/link1", ...] 

_LINKS = { 
    'polls.can_vote' : lambda u: ["/user/specific/link/" + u.id], 
    'polls.can_close': lambda u: ['/static/link/1', 'static/link/2'], 
    'polls.can_open' : more_elaborate_list_of_links_for_a_perm 
} 

def gen_links(user): 
    # get_all_permissions also gets permissions for users groups 
    perms = user.get_all_permissions() 
    return sum((_LINKS[p](user) for p in perms if p in _LINKS), []) 

Có lẽ nhiều khác phương pháp tiếp cận.

+1

Bạn sẽ tạo danh sách các liên kết để cung cấp cho người dùng sử dụng hệ thống cấp phép tích hợp của django như thế nào? – slypete

+1

Đối với hồ sơ, tôi không chọn câu trả lời này là tốt nhất. Tôi không nghĩ vậy. – slypete

1

Nếu bạn không cần ACL mỗi đối tượng thực, thì bạn chỉ có thể sử dụng hệ thống cấp phép Django. Để có danh sách tất cả các quyền có sẵn:

from django.contrib.auth.models import Permission 
perms = Permission.objects.all() 

API for other authentication and authorization sources, vì vậy bạn không cần phải gắn với bảng quyền này.

Bạn có thể hack hệ thống Django này để phù hợp với nhu cầu của bạn về mô hình ủy quyền này (RBAC) hoặc bạn có thể đưa ra giải pháp giống như ACL.

+0

bất kỳ gợi ý nào cho một acl cho mỗi đối tượng? – gpilotino

4

Chúng tôi đã gặp sự cố tương tự. Nhóm của Django không thực sự phù hợp với điều này, nhưng bạn có thể shoehorn chúng trong.

Cách chúng tôi thực hiện như sau:

Mỗi đối tượng được kiểm soát truy cập có mối quan hệ ManyToMany với bảng nhóm. Mỗi nhóm được sử dụng để xác định một loại quyền cụ thể ("có thể xem thông tin cơ bản về bệnh nhân", "có thể chỉnh sửa thông tin liên hệ của bệnh nhân", v.v.). Người dùng được thêm vào các nhóm mà họ cần phải có quyền (trong ví dụ của bạn chỉ nhìn thấy bệnh nhân trong bệnh viện này, bạn có thể có một nhóm "thung lũng-xem-bệnh viện").

Sau đó, khi bạn đi để hiển thị danh sách các bản ghi cho người dùng, bạn lọc dựa trên sự kết hợp của hai nhóm. Người dùng phải có tất cả các quyền liên quan của nhóm để xem một đối tượng nhất định.

Nếu hệ thống của bạn yêu cầu, bạn có thể giữ một ManyToMany riêng biệt của các quyền phủ định hoặc quyền đọc/ghi riêng biệt. Bạn cũng có thể xác định một tập hợp các nhóm meta (bác sĩ, y tá) dẫn đến bộ lọc tra cứu của bạn truy xuất tập con thực sự của các quyền.

Khi vấn đề thanh liên kết của bạn xuất hiện, bạn có thể tạo các bộ lọc theo cách lập trình dựa trên các lớp đối tượng người dùng có thể xem hoặc chỉnh sửa, sau đó sử dụng hàm get_absolute_url() (có thể gọi là get_index_url())) để trả về các liên kết cho chỉ mục của mỗi lớp đối tượng.

Bởi vì tất cả điều này là khá phức tạp, có thể bạn sẽ muốn làm một số cấp bộ nhớ đệm cho những thứ này, nhưng làm cho nó hoạt động trước khi bạn bận tâm tối ưu hóa. Nó có thể, và nó ít xấu xí trong mã hơn là trong lời nói.

+0

Tôi đã kết thúc chuyến đi này với ứng dụng của chúng tôi, nhưng nó không lý tưởng. Tôi thấy hiệu suất đã giảm một chút. Tôi đang tìm nơi khác để có giải pháp ACL tốt hơn – Gevious

+0

Điều này không thể mở rộng được. Bất kỳ ý tưởng về ACL? – user710907

2

Tôi đã gặp sự cố tương tự cách đây không lâu. Giải pháp của chúng tôi đã thực hiện thủ thuật, mặc dù nó có thể quá đơn giản cho tình huống của bạn. Giống như mọi người đang đề xuất, chúng tôi đã sử dụng hệ thống cấp phép django để kiểm soát những tương tác của người dùng với các mô hình. Tuy nhiên, chúng tôi không chỉ cố gắng nhóm người dùng, chúng tôi cũng nhóm các đối tượng thông qua một GenericForeignKey.

Chúng tôi đã xây dựng một mô hình liên kết với chính nó để cho phép phân cấp được phát triển.

class Group(models.Model): 
    name = models.CharField(...) 
    parent = models.ForeignKey('self', blank=True, null=True) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 
    ... 

Để làm cho nó làm việc, chúng tôi cũng tạo ra một mô hình để đóng vai trò như lý lịch thành viên django mô hình của người dùng. Tất cả nó chứa là một ManyToManyField được liên kết với mô hình Nhóm ở trên. Điều này cho phép chúng tôi cấp cho người dùng quyền truy cập vào 0 hoặc nhiều Nhóm theo yêu cầu. (documentation)

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    groups = models.ManyToManyField(Group) 
    ... 

này đã cho chúng tôi tốt nhất của cả hai thế giới và giữ chúng ta khỏi cố gắng bót đi giày tất cả mọi thứ vào hệ thống cho phép django của. Tôi đang sử dụng thiết lập cơ bản này để kiểm soát quyền truy cập của người dùng vào nội dung thể thao (một số người dùng có thể truy cập toàn bộ giải đấu, một số chỉ một hoặc hai hội nghị, một số chỉ có quyền truy cập vào từng nhóm) và hoạt động tốt trong tình huống đó. Nó có lẽ có thể là một tổng quát đủ để phù hợp với nhu cầu của bạn.

1

Trên trang web dành cho chuyên gia về rượu vang Pinot Noir, chúng tôi đã tạo quyền truy cập cho mỗi đối tượng dựa trên một số tiêu chí khác nhau. Nếu liên kết trong nước có trường tham chiếu khớp với tên miền của một nhà máy rượu nổi bật thì người dùng sẽ nhận được 'mã thông báo nhà máy' mở rộng tới tất cả các bài viết, ghi chú nếm, v.v. liên quan đến nhà máy rượu đó. Chúng tôi sử dụng 'mã thông báo có tên' để cung cấp cho aways tại các sự kiện nếm và họ đã cấp quyền truy cập vào các phần cụ thể của trang web. Chúng tôi thậm chí sử dụng điều này để cấp một số loại quyền nhất định cho trình thu thập dữ liệu của công cụ tìm kiếm và sau đó đảm bảo rằng các liên kết đến từ các công cụ tìm kiếm đó có cùng quyền như spider (ví dụ: không có trò chơi che giấu).

Phiên bản ngắn gọn là bạn có thể tạo một lớp (chúng tôi gọi chúng là TokenBuckets chứa Tokens) và mỗi đối tượng (trên trang chi tiết hoặc trang danh sách hoặc bất kỳ thứ gì) có thể hỏi TokenBucket của người dùng truy cập được cho phép.

Về cơ bản đó là một loại hệ thống ACL kỳ lạ. Nó không khó để tạo ra cơ chế. Tất cả các phép thuật là trong việc xác định trong những hoàn cảnh nào mà các thẻ đi vào xô.

0

Chúng tôi đã sử dụng hệ thống cơ sở vai trò cho một vấn đề tương tự. Về cơ bản, người dùng có quyền giả định các vai trò khác nhau.

Xem chức năng đã được trang trí:

def needs_capability(capability,redirect_to="/cms/"): 
    def view_func_wrapper(view_func): 
     def wrapped_view_func(request,*args,**kwargs): 
      if not request.role._can(capability): 
       return HttpResponseRedirect(redirect_to) 
      return view_func(request,*args,**kwargs) 
     return wrapped_view_func 
    return view_func_wrapper 

Phần còn lại của sự kỳ diệu bên trong thuộc tính request.role mà có bộ bên trong một bộ xử lý ngữ cảnh. Người dùng được xác thực có vai trò, đối với khối lượng chưa rửa một DummyRole.

Tiếp cận thông tin bị hạn chế hơn nữa bên trong mẫu:

{% if not request.role.can.view_all_products %} 
      Lots of products, yeah! 
{% endif %} 

Không phải là giải pháp sạch theo ý kiến ​​của tôi, nhưng làm việc như mong đợi.

1

Câu hỏi này đã được hỏi trong tháng 10 năm 2009 và vấn đề vẫn còn tồn tại trong tháng 7 năm 2012.

Tôi đã tìm kiếm một ứng dụng ứng dụng có vai trò tốt và đã tìm thấy django-permission là kết quả tốt nhất.

Ba tính năng quan trọng mà tôi cần là Vai trò, xem trang tríTemplatetag; rõ ràng là django-permissions có tất cả chúng. Đọc nó là docs để sử dụng.

Hạn chế duy nhất là nó đang được phát triển.

Các vấn đề liên quan