[英]How to prevent a url from changing when loading the same template with different data in Django
[英]How to prevent user changing URL <pk> to see other submission data Django
我是 web 开发世界、Django 以及需要保护 URL 的应用程序的新手,这些用户更改 foo/bar/ pk以访问其他用户数据。
有没有办法防止这种情况? 或者是否有一种内置方法可以防止这种情况在 Django 中发生?
例如: foo/bar/22
可以更改为foo/bar/14
并公开过去的用户数据。
我已经阅读了有关该主题的几个问题的答案,但我运气不佳,无法清楚,连贯地解释这一点以及防止这种情况的方法。 我对此不太了解,所以我不知道如何表达这个问题以正确调查它。 请像我 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
您甚至可以编写一个中间件 ,将用户重定向到他们的页面/foo/bar/userid
- 如果没有登录,则写入登录页面。
如果你想控制每个对象的访问,我建议使用django-guardian 。 以下是配置设置和安装后的样子(这是来自django-guardian的文档 ):
>>> 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
如果您不想使用外部库,也可以在Django的视图中进行操作 。
这可能是这样的:
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...
只需检查主键检索的对象是否属于请求用户。 在视图中这将是
if some_object.user == request.user: ...
这要求表示对象的模型具有对User模型的引用。
您将要查看用户身份验证和授权,这两者都是由Django的Auth软件包提供的 。 这两件事之间也存在很大差异。
身份验证确保某人是他们所说的人。 想一想,登录。你会得到一个人的全部用户名和密码来证明他们是该帐户的所有者。
授权确保某人能够访问他们尝试访问的内容。 因此,例如普通用户将无法仅切换PK。
我在上面提供的链接中详细记录了授权。 我将从那里开始并运行一些示例代码。 希望能回答你的问题。 如果没有,希望它能为您提供足够的信息,让您回来询问更具体的问题。
在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。
在我的项目中,对于多个模型/表,用户应该只能看到他/她输入的数据,而不能看到其他用户输入的数据。 对于这些模型/表,有一个用户列。
在列表视图中,这很容易实现,只需过滤传递给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模板,就可以了。
这是一个反复出现的问题,也意味着一个严重的安全漏洞。 我的贡献是这样的:
有2个基本方面需要注意。
首先是观点:
a) 注意向基于函数的视图添加装饰器(例如@login_required)或向基于类的 function(例如 LoginRequiredMixin)添加混合。 我发现官方 Django 文档对此非常有帮助( https://docs.djangoproject.com/en/4.0/topics/auth/default/ )。
b) 在您看来,当您定义要检索或插入的数据(GET 或 POST 方法)时,必须按该用户的 ID 过滤用户的数据。 像这样的东西:
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=User.objects.filter(pk=self.request.user.id))
return super().get(request, *args, **kwargs)
第二个方面是URL:
在 URL 中,您还应该将 URL 限制为视图中定义的 pk。 像这样的东西:
path('int:pk/blog-add/', AddBlogView.as_view(), name='blog-add'),
根据我的经验,这可以防止用户看到另一个用户的数据,只需更改 URL 中的数字即可。
希望能帮助到你。
在 django CBV(基于类的视图)中,您可以通过比较用户输入的 pk 和当前登录的用户来防止这种情况:
注:我在django 4和python 3.9测试过。
from django.http import HttpResponseForbidden
class UserDetailView(LoginRequiredMixin, DetailView):
model = your_model
def dispatch(self, request, *args, **kwargs):
if kwargs.get('pk') != self.request.user.pk:
return HttpResponseForbidden(_('You do not have permission to view this page'))
return super().dispatch(request, *args, **kwargs)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.