1

假设我正在创建一个表单,并且我正在通过绑定传递一些隐藏值,这些值不能更改。我的问题是如何测试恶意用户是否更改了此隐藏值?我不确定表单中的绑定数据到底是什么以及初始数据之间的区别。

在 Django 的forms.py中有一个名为changed_data的属性,但我不知道是否有帮助。

演示代码:

表格.py

class ConfirmForm(forms.Form):
    client_id = forms.CharField(widget=forms.HiddenInput())
    identifier = forms.CharField(widget=forms.HiddenInput())

    def clean(self):
        # Maybe here the validation process of cliend_id and identifier like:
        clean_client_id = self.cleaned_data.get('client_id')
        clean_identifier = self.cleaned_data.get('identifier')
        if last_client_id == clean_client_id and 
           last_identifier == clean_identifier:
            return self.cleaned_data
        else:
            raise forms.ValidationError("False data.")

视图.py

def form_confirm_handler(request):
    if request.method == 'POST':
        form = ConfirmForm(request.POST)
        if form.is_valid():
            #Do something...
            return redirect('home:index')

    #The following values are not fixed. Are generated variables!
    bound_data = {'client_id':'123456','identifier':'wuiy5895'}
    form = ConfirmForm(bound_data)
    return render(request, 'client/theform.html', {'form':form})

html模板

<form action="{% url 'client:confirm' %}" method="post">
    <p>Do you really want to proceed?</p>
    {% csrf_token %}
    {{ form.client_id }}
    {{ form.identifier }}
    <button id="submit" type="submit" name="submit" class="btn" value="accept">Accept</button>
    <button id="cancel" type="submit" name="cancel" class="btn btn-primary" value="cancel">Cancel</button>
</form>

提前致谢!

4

3 回答 3

5

我找到了 4 个(简单的)可能的解决方案来解决这个问题。

对 Django 最有效的解决方案是:

class TheFormName():
    client_id = forms.CharField(show_hidden_initial=True, widget=forms.HiddenInput())
    identifier = forms.CharField(show_hidden_initial=True, widget=forms.HiddenInput())

def clean(self):
    if self.has_changed():
        raise forms.ValidationError('Fields are not valid.')

    return self.cleaned_data

第二种解决方案是使用changed_data来查看发生了什么变化:

def clean(self):
    for field_name in self.changed_data:
        # loop through the fields which have changed
        print "field {} has changed. New value {}".format(field_name, cleaned_data['field_name']

对于我的情况是这样翻译的,但与方法完全相同has_changed()

def clean(self):
    if len(self.changed_data) > 0:
        raise forms.ValidationError('Fields are not valid.')

    return self.cleaned_data

另一个看起来更像黑客的解决方案是:

self.cleaned_data['cliend_id'] == self.instance.cliend_id
self.cleaned_data['identifier'] == self.instance.identifier

最终的解决方案有点复杂,是在clean()方法内部(和视图之外)使用会话。来自Django 文档的示例:

from django.contrib.sessions.backends.db import SessionStore
import datetime
s = SessionStore()
s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10)
s.save()
s.session_key
>>> '2b1189a188b44ad18c35e113ac6ceead'

s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
s['last_login']

这篇文章也很有用在 Django 1.4 中,未记录的 Form.has_changed() 和 Form.changed_data 是否按预期工作?由@LarsVegas 提供

于 2013-04-13T13:10:09.817 回答
0

我一直在考虑是否可以使用会话变量。

def form_confirm_handler(request):
    if request.method == 'POST':
        form = ConfirmForm(request.POST)
        if form.is_valid():

            if form.cleaned_data.get['client_id'] == request.session.get('client_id'):
                //.....
            else:
                //.....

            //delete the session after comparing
            del request.session['client_id']
            del request.session['identifier']

            return redirect('home:index')

    #The following values are not fixed. Are generated variables!

    request.session['client_id'] = '123456'
    request.session['identifier'] = 'wuiy5895'

    bound_data = {
        'client_id': request.session.get('client_id'), 
        'identifier': request.session.get('identifier')
    }

    form = ConfirmForm(bound_data)
    return render(request, 'client/theform.html', {'form':form})
于 2013-04-13T11:59:21.313 回答
0

创建一个名为的新隐藏字段temper_seal

temper_seal = forms.CharField(widget=forms.HiddenInput())

将 的初始值设置为和temper_seal的哈希值,client_id以及identifier一些只有您的服务器知道的随机常量字符串。

当表单返回用户数据时,对 和 的值client_id以及identifier之前使用的常量字符串进行哈希处理。temper_seal将此值与隐藏字段中提交的值进行比较。如果它们相同,则用户没有更改client_id和中的数据identifier

于 2013-04-12T17:18:21.923 回答