Tôi đang cố triển khai kiểm tra bảo mật dựa trên hàng cho các mô hình Django. Ý tưởng là khi tôi truy cập trình quản lý mô hình, tôi chỉ định một số thông tin bổ sung được sử dụng trong truy vấn cơ sở dữ liệu để chỉ các cá thể được phép mới được tìm nạp từ cơ sở dữ liệu.Mô hình Django - chuyển thông tin bổ sung cho người quản lý
Ví dụ: chúng tôi có thể có hai kiểu: Người dùng và, nói, Mục. Mỗi mục thuộc về một số người dùng và người dùng có thể được kết nối với nhiều mục. Và để có một số hạn chế, theo đó người dùng có thể thấy hoặc không thể thấy các mục của một người dùng khác. Tôi muốn tách riêng những hạn chế này từ các yếu tố truy vấn khác và viết một cái gì đó như:
items = Item.scoped.forceRule('user1').all() # all items visible for 'user1'
hoặc
# show all items of 'user2' visible by 'user1'
items = Item.scoped.forceRule('user1').filter(author__username__exact = 'user2')
Để đạt được điều này tôi đã thực hiện như sau:
class SecurityManager(models.Manager):
def forceRule(self, onBehalf) :
modelSecurityScope = getattr(self.model, 'securityScope', None)
if modelSecurityScope :
return super(SecurityManager, self).get_query_set().filter(self.model.securityScope(onBehalf))
else :
return super(SecurityManager, self).get_query_set()
def get_query_set(self) :
#
# I need to know that 'onBehalf' parameter here
#
return super(SecurityManager, self).get_query_set()
class User(models.Model) :
username = models.CharField(max_length=32, unique=True)
class Item(models.Model) :
author = models.ForeignKey(User)
private = models.BooleanField()
name = models.CharField(max_length=32)
scoped = SecurityManager()
@staticmethod
def securityScope(onBehalf) :
return Q(author__username__exact = onBehalf) | Q(bookmark__private__exact = False)
Đối với ví dụ cho thấy nó hoạt động tốt , nhưng chết theo sau:
items = Item.scoped.forceRule('user1').filter(author__username__exact = 'user2') # (*)
items2 = items[0].author.item_set.all() # (**)
Chắc chắn, items2
được điền bởi tất cả các mục của 'user2', không chỉ những mục phù hợp với quy tắc. Đó là bởi vì khi tất cả() được thực hiện SecurityManager.get_query_set()
không có thông tin về bộ hạn chế. Mặc dù nó có thể. Ví dụ, trong forceRule() tôi có thể thêm một trường cho mỗi cá thể và sau đó, nếu tôi có thể truy cập trường đó từ người quản lý, hãy áp dụng quy tắc cần thiết.
Vì vậy, câu hỏi là - có cách nào để chuyển đối số được cung cấp cho forceRule()
trong tuyên bố (*)
cho người quản lý, được gọi trong tuyên bố (**)
.
Hoặc một câu hỏi khác - tôi có đang làm những điều kỳ lạ mà tôi không nên làm gì cả?
Cảm ơn bạn.
Tôi cũng đang đối mặt với trường hợp sử dụng tương tự, tôi tự hỏi cách bạn xoay xở để giải quyết vấn đề này? cảm ơn! – ultrajohn