强制将用户发送到自定义QuerySet

时间:2010-04-09 17:33:05

标签: django django-models

我正在尝试保护应用程序,以便用户只能看到分配给它们的对象。我有一个自定义QuerySet适用于此,但我正试图找到一种方法来强制使用这个附加功能。这是我的模型:

class Inquiry(models.Model):   
    ts = models.DateTimeField(auto_now_add=True)
    assigned_to_user = models.ForeignKey(User,
            blank=True,
            null=True,
            related_name="assigned_inquiries")
    objects = CustomQuerySetManager()
    class QuerySet(QuerySet):
        def for_user(self, user):       
            return self.filter(assigned_to_user=user)

(CustomQuerySetManager记录为over here,如果它很重要。)

我正在尝试强制所有内容使用此过滤,以便其他方法引发异常。例如:

Inquiry.objects.all() ## Should raise an exception.
Inquiry.objects.filter(pk=69) ## Should raise an exception.
Inquiry.objects.for_user(request.user).filter(pk=69) ## Should work.
inqs = Inquiry.objects.for_user(request.user) ## Should work.
inqs.filter(pk=69) ## Should work.

在我看来,应该有一种方法来强制这些对象的安全性,只允许某些用户访问它们。

我不关心这可能会如何影响管理界面。

4 个答案:

答案 0 :(得分:0)

AFAIK,Django还没准备好在域对象/ DAO级别上提供安全性。

我不知道有什么方法可以“通过这种情况强制所有查询过滤”。你当然可以覆盖所有QuerySet方法以确保这一点,但它有点笨拙和乏味。

执行此操作的常用方法是在视图中保护代码。这对于曾经做过AOP的人来说很骇人听闻,但它确实有用。

答案 1 :(得分:0)

我假设您这样做的原因是因为您希望确保您或其他开发人员永远不会忘记用户过滤X模型。

我认为解决这个问题的正确方法不一定是让它抛出异常,而是让Django的测试框架的用户和编写测试以确保视图/任何不返回其他用户的数据。

答案 2 :(得分:0)

我建议在模型方法中隔离所有查询集生成,这样可以更容易在代码审查期间查看错误查询,并更容易开发检查安全性的测试。如果您需要执行某种检查,那么Record Ownership screener middleware可能会有所帮助。否则尝试另一种方法,如django-authority

(来自问题How to enforce account based separation in DjangoHow would one organize this...

答案 3 :(得分:0)

管理器中的所有内容都贯穿函数get_query_set()。你不能将它用作阻塞点并检查是否存在必须在所有情况下设置的参数?因此,如果您没有viewing_user关键字参数,则抛出异常。类似的东西:

def get_query_set(self):
    if not self.viewing_user:
        raise MyCustomException
    return super(CustomQuerySetManager, self).get_query_set()