2017-11-21 74 views
5

Tôi đang cố gắng cung cấp giao diện cho người dùng ghi các truy vấn tùy chỉnh trên cơ sở dữ liệu. Tôi cần đảm bảo rằng họ chỉ có thể truy vấn các hồ sơ mà họ được phép. Để thực hiện điều đó, tôi quyết định áp dụng điều khiển truy cập dựa trên hàng bằng cách sử dụng django-guardian.Kiểm soát quyền truy cập và kiểm soát cấp hàng nguyên qua nhiều mô hình trong Django

Sau đây là cách schemas của tôi trông giống như

class BaseClass(models.Model): 
    somefield = models.TextField() 
    class Meta: 
     permissions = (
      ('view_record', 'View record'), 
     ) 

class ClassA(BaseClass): 
    # some other fields here 
    classb = models.ForeignKey(ClassB) 

class ClassB(BaseClass): 
    # some fields here 
    classc = models.ForeignKey(ClassC) 

class ClassC(BaseClass): 
    # some fields here 

Tôi muốn để có thể sử dụng get_objects_for_group như sau:

>>> group = Group.objects.create('some group') 
>>> class_c = ClassC.objects.create('ClassC') 
>>> class_b = ClassB.objects.create('ClassB', classc=class_c) 
>>> class_a = ClassA.objects.create('ClassA', classb=class_b) 
>>> assign_perm('view_record', group, class_c) 
>>> assign_perm('view_record', group, class_b) 
>>> assign_perm('view_record', group, class_a) 
>>> get_objects_for_group(group, 'view_record') 

này mang lại cho tôi một QuerySet. Tôi có thể sử dụng BaseClass mà tôi đã định nghĩa ở trên và viết truy vấn thô lên các lớp liên quan khác không?

>>> qs.intersection(get_objects_for_group(group, 'view_record'), \ 
        BaseClass.objects.raw('select * from table_a a' 
              'join table_b b on a.id=b.table_a_id ' 
              'join table_c c on b.id=c.table_b_id ' 
              'where some conditions here')) 

Phương pháp này có hợp lý không? Có cách nào tốt hơn để giải quyết vấn đề này không?

Cảm ơn!

Edit:

Một cách khác để giải quyết vấn đề có thể được tạo ra một bảng riêng biệt cho mỗi người dùng. Tôi hiểu sự phức tạp mà điều này có thể thêm vào đơn đăng ký của tôi nhưng:

  • Số lượng người dùng sẽ không quá 100 trong một thời gian dài. Không phải là một ứng dụng tiêu dùng.
  • Mỗi trường hợp sử dụng của chúng tôi, tôi không cần phải truy vấn qua các bảng này. Tôi sẽ không viết một truy vấn mà cần phải tổng hợp bất cứ điều gì từ table1, table2, table3 thuộc về cùng một mô hình.
  • Việc duy trì một bảng riêng biệt cho mỗi khách hàng có thể có lợi thế.

Bạn có nghĩ đây là phương pháp khả thi không?

+0

Chỉ cần xác thực rằng tôi không thể thực hiện giao lộ trên RawQuerySet. – ertan

Trả lời

2

Tôi nghĩ bạn đã biết mình cần làm gì. Từ bạn đang tìm kiếm là đa nhiệm. Mặc dù nó không phải là một bảng cho mỗi khách hàng. Phù hợp nhất cho bạn sẽ là một lược đồ cho mỗi khách hàng. Thật không may, bài viết hay nhất tôi có về đa nhiệm không còn khả dụng nữa. Xem nếu bạn có thể tìm thấy phiên bản được lưu trong bộ nhớ cache: https://msdn.microsoft.com/en-us/library/aa479086.aspx nếu không, có rất nhiều bài viết có sẵn trên internet.

Một cách tiếp cận khả thi khác là xem custom managers. Bạn có thể viết một trình quản lý tùy chỉnh cho từng Mô hình-Khách hàng và truy vấn nó theo đó. Nhưng tất cả điều này sẽ dẫn đến sự phức tạp của ứng dụng và sẽ sớm thoát ra khỏi bàn tay của bạn. Bất kỳ lỗi nào trong lớp bảo mật ứng dụng đều là một cơn ác mộng đối với bạn.

Cân nhắc cả hai tôi muốn có khuynh hướng nói giải pháp đa nhiệm như bạn đã nói trong bản chỉnh sửa của mình là cách tiếp cận tốt nhất.

+0

Tôi nghĩ rằng tôi sẽ kết thúc với Row Level Security trên PostgreSQL: https://www.postgresql.org/docs/9.5/static/ddl-rowsecurity.html. Bài viết này đã giúp tôi rất nhiều để thu hút người dùng cấp ứng dụng bằng các chính sách sau khi đăng bài: https://blog.2ndquadrant.com/application-users-vs-row-level-security/ – ertan

+0

Đọc thú vị. Cám ơn vì đã chia sẻ. Nhưng có một vấn đề tôi thấy. Chi phí của việc tạo ra các chính sách mới và duy trì tính đồng bộ giữa lớp db và lớp ứng dụng không xứng đáng. –

+1

Tạo chính sách cho mỗi bảng là phí trên có, nhưng bạn chỉ phải thực hiện một lần. Nếu bạn viết một kịch bản để làm như vậy và kiểm tra nó vào repo, nó không cảm thấy xấu như vậy. Re: đồng bộ hóa db và lớp ứng dụng. Trên thực tế, điều này chủ yếu được xử lý bằng cách đặt biến phiên phù hợp với một dòng mã và phần còn lại được xử lý bên trong các chính sách. Điểm duy nhất là nếu trường cụ thể này thay đổi thông qua di chuyển, điều đó có thể tạo ra lỗ hổng bảo mật. Tôi đang lập kế hoạch để giảm thiểu điều này với một số xét nghiệm tích hợp. Tôi cảm thấy nó đơn giản hơn để duy trì so với multitenancy. – ertan

2

Sau khi nghiên cứu nhiều tùy chọn, tôi phát hiện ra rằng tôi có thể giải quyết vấn đề này ở cấp cơ sở dữ liệu bằng cách sử dụng Row Level Security trên PostgreSQL. Nó kết thúc là dễ nhất và thanh lịch nhất.

This article đã giúp tôi rất nhiều để thu hút người dùng cấp ứng dụng bằng chính sách PostgreSQL.

Những gì tôi học được bằng cách thực hiện nghiên cứu của tôi là:

  • bảng riêng biệt vẫn có thể là một lựa chọn trong tương lai khi các khách hàng tiềm năng có thể ảnh hưởng đến màn trình diễn truy vấn của nhau kể từ khi họ được phép chạy các truy vấn tùy ý.

  • Cố gắng giải quyết nó ở cấp ORM gần như là không thể nếu bạn định sử dụng truy vấn thô hoặc ad-hoc.

-1

Trước tiên, bạn nên cung cấp cho chúng tôi thêm chi tiết, cách thiết lập kiến ​​trúc của bạn và được xây dựng, với django để chúng tôi có thể trợ giúp bạn. Bạn đã triển khai API chưa? bằng cách sử dụng mẫu django không thực sự là một ý tưởng tốt nếu bạn đang xây dựng một ứng dụng quy mô lớn, tiêu thụ rất nhiều dữ liệu.Bởi vì điều này có thể ảnh hưởng đến tải truy vấn ồ ạt.I có thể đề xuất trích xuất front-end của bạn từ backend.

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