1

我在我的一个项目中使用了 Django 的内置用户模型。当然,用户应该是可编辑的。由于这是最方便的解决方案,我开始使用 Django 自己的 UserChangeForm 提供用户编辑表单。UserChangeForm 基本上是 UserModel 的 ModelForm,因此可以更改 User 模型的所有字段。

我不希望用户能够更改每个字段。所以,我的第一个想法是将整个 UserChangeForm 传递到模板中,但只呈现我需要的字段(比如“用户名”和“电子邮件”)。我还希望只有超级用户能够更改用户名,因此只有在您是超级用户时才会呈现此字段。

基本代码如下所示:

查看功能

def edit_user(request, pk):
    ...    #code to ensure not everyone can edit every user
    user = User.objects.get(pk=pk)
    if request.method == 'POST':
        form = UserChangeForm(request.POST, instance=user)
        if form.is_valid:
            form.save()
           ...    #redirect
    else:
        form = UserChangeForm(instance=user)
    ...    # render template

模板中的表格

<form action="{{ request.path }}" method="post">
    {% csrf_token %}
    {% if user.is_superuser %}
        {{ form.username }}
    {% endif %}
    {{ form.email }}
    <button type="submit">Save</button>
</form>

现在,我的问题是:这个解决方案的安全性如何?我没有做任何事情来阻止攻击者添加例如用户名字段,即使他不是超级用户。这样,他将使用附加数据填充 POST 数据,然后将其发送到视图函数并用于更新 User 对象。这可能会变得非常危险,因为原始的 UserChangeForm 还包含一个字段“is_superuser”。

我自己尝试破解表格以测试我的怀疑。我以普通用户身份登录,通过开发者工具添加用户名输入并提交表单。结果是一个例外:

Traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  20.                 return view_func(request, *args, **kwargs)
File "/Users/joker/Development/wiki2099/wiki2099/apps/accounts/views.py" in edit_user
  69.             form.save()
File "/Library/Python/2.7/site-packages/django/forms/models.py" in save
  364.                              fail_message, commit, construct=False)
File "/Library/Python/2.7/site-packages/django/forms/models.py" in save_instance
  74.                          " validate." % (opts.object_name, fail_message))

Exception Type: ValueError at /accounts/edit/12/
Exception Value: The User could not be changed because the data didn't validate.

我不确定这是否意味着这种攻击是不可能的,或者我只是没有做对。我认为,CSRF 令牌可以防止此类黑客攻击,但我在文档中没有发现任何关于这件事的信息。谁能启发我?是否有任何机制可以防止攻击者使用未呈现的表单字段,它是如何工作的?

提前致谢!

4

2 回答 2

1

据我所知,CSRF 令牌只能防止 CSRF 攻击,并且不会对更改数据的权限做任何事情。

虽然不清楚您是否只是在用户不是超级用户的情况下不呈现该字段,或者您根本没有添加它self.fields。您应该使用第二种方式,甚至为超级用户提供单独的表单。

于 2012-09-08T16:18:11.097 回答
1

如果您想限制用户可以编辑的字段,那么您需要定义一个包含模型字段子集的表单

如果您没有在模板中呈现表单字段,但用户为其提交了数据,那么 Django 将照常处理它。查看回溯后,我不明白为什么您的尝试失败了,但是使用您描述的方法进行攻击是可能的。

csrf 保护在这里帮不了你。其目的是防止第三方欺骗您的用户向您的网站提交数据,而不是防止带有额外字段的手工制作的 POST 数据。

如果您故意不在模板中呈现字段,还有一个需要注意的问题:如果省略的字段不是必需的,那么缺少的 POST 值将被解释为空字符串,验证,并且您的数据将被擦除。

于 2012-09-08T16:43:45.507 回答