如何防止用户更改URL <pk>以查看其他提交数据Django </pk>

时间:2014-08-14 16:04:57

标签: python django model-view-controller

我是网络开发世界,Django以及需要保护来自更改foo / bar / pk 以访问其他用户数据的用户的URL的应用程序的新手。

有没有办法防止这种情况发生?或者是否有一种内置方法可以防止在Django中发生这种情况?

例如为: foo/bar/22可以更改为foo/bar/14并公开过去的用户数据。

我已经阅读了关于这个主题的几个问题的答案,我在一个答案中没有运气,这个答案可以清楚而连贯地解释这个以及防止这种情况的方法。我对此并不了解,所以我不知道该怎么说这个问题来正确调查它。请向我解释,就像我5岁。

6 个答案:

答案 0 :(得分:5)

有几种方法可以实现这一目标:

如果您有登录的概念,只需将URL限制为:

/foo/bar/

并在代码中user=request.user并仅显示已登录用户的数据。

另一种方式是:

/foo/bar/{{request.user.id}}/

并在视图中:

def myview(request, id):
    if id != request.user.id:
        HttpResponseForbidden('You cannot view what is not yours') #Or however you want to handle this

您甚至可以write a middleware将用户重定向到他们的页面/foo/bar/userid - 如果没有登录则可以重定向到登录页面。

答案 1 :(得分:4)

如果您想控制每个对象的访问权限,我建议您使用django-guardian。以下是配置设置并进行安装后的样子(来自django-guardian's docs):

>>> from django.contrib.auth.models import User
>>> boss = User.objects.create(username='Big Boss')
>>> joe = User.objects.create(username='joe')
>>> task = Task.objects.create(summary='Some job', content='', reported_by=boss)
>>> joe.has_perm('view_task', task)
False

如果您不想使用外部图书馆,还可以使用外部图书馆in Django's views

以下是看起来的样子:

from django.http import HttpResponseForbidden
from .models import Bar

def view_bar(request, pk):
    bar = Bar.objects.get(pk=pk)
    if not bar.user == request.user:
        return HttpResponseForbidden("You can't view this Bar.")
    # The rest of the view goes here...

答案 2 :(得分:3)

只需检查主键检索的对象是否属于请求用户。在视图中,这将是

if some_object.user == request.user: ...

这要求表示对象的模型具有对用户模型的引用。

答案 3 :(得分:2)

您将要查看由Django's Auth package提供的用户身份验证和授权。这两件事之间也存在很大差异。

身份验证确保某人是他们所说的人。想一想,登录。你会得到一个人的全部用户名和密码,以证明他们是该帐户的所有者。

授权确保某人能够访问他们尝试访问的内容。因此,例如普通用户将无法只切换PK。

我在上面提供的链接中详细记录了授权。我将从那里开始并运行一些示例代码。希望能回答你的问题。如果没有,希望它能为您提供足够的信息,让您回来询问更具体的问题。

答案 4 :(得分:2)

在django中,当前登录的用户在您的视图中可用作请求对象的属性user

我们的想法是首先按登录用户过滤模型,然后如果有任何结果只显示这些结果。

如果用户试图访问不属于他们的对象,请不要显示该对象。

处理所有这些问题的一种方法是使用get_object_or_404快捷方式功能,如果找不到与给定参数匹配的对象,则会引发404错误。

使用它,我们可以将主键和当前登录用户传递给此方法,如果它返回一个对象,这意味着主键属于该用户,否则它将返回404,就好像页面没有不存在。

将其插入您的视图非常简单:

from django.shortcuts import get_object_or_404, render

from .models import YourModel

def some_view(request, pk=None):
    obj = get_object_or_404(YourModel, pk=pk, user=request.user)
    return render(request, 'details.html', {'object': obj})

现在,如果用户尝试访问带有不属于他们的pk的链接,则会引发404。

答案 5 :(得分:2)

在我的项目中,对于多个模型/表,用户应该只能看到他/她输入的数据,而不能看到其他用户输入的数据。对于这些模型/表,有一个用户列。

在列表视图中,这很容易实现,只需过滤传递给model.user = loggged_id.user的列表视图的查询集。

但是对于详细/更新/删除视图,在URL中看到PK,可以想象用户可以编辑URL中的PK并访问另一个用户的行/数据。

我正在使用Django内置的基于视图的视图。

URL中的PK视图已经具有LoginRequiredMixin,但这并不能阻止用户更改URL中的PK。

我的解决方案:&#34;登录用户拥有此行Mixin&#34;  (DoesLoggedInUserOwnThisRowMixin) - 覆盖get_object方法并在那里进行测试。

from django.core.exceptions import PermissionDenied

class DoesLoggedInUserOwnThisRowMixin(object):

    def get_object(self):
        '''only allow owner (or superuser) to access the table row'''
        obj = super(DoesLoggedInUserOwnThisRowMixin, self).get_object()
        if self.request.user.is_superuser:
            pass
        elif obj.iUser != self.request.user:
            raise PermissionDenied(
                "Permission Denied -- that's not your record!")
        return obj

瞧!

只需将mixin放在LoginRequiredMixin之后的视图类定义行上,并使用输出消息的403.html模板,就可以了。