我是网络开发世界,Django以及需要保护来自更改foo / bar / pk 以访问其他用户数据的用户的URL的应用程序的新手。
有没有办法防止这种情况发生?或者是否有一种内置方法可以防止在Django中发生这种情况?
例如为:
foo/bar/22
可以更改为foo/bar/14
并公开过去的用户数据。
我已经阅读了关于这个主题的几个问题的答案,我在一个答案中没有运气,这个答案可以清楚而连贯地解释这个以及防止这种情况的方法。我对此并不了解,所以我不知道该怎么说这个问题来正确调查它。请向我解释,就像我5岁。
答案 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。
我的解决方案:"登录用户拥有此行Mixin" (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模板,就可以了。