假设我正在创建一个表单,并且我通过绑定传递一些隐藏的值,不能更改。我的问题是如何测试恶意用户是否更改了此隐藏值? 我不确定表单中绑定数据到底是什么以及初始值之间的区别。
在Django中,forms.py是一个名为changed_data的属性,但我不知道是否可以提供帮助。
示范代码:
forms.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.")
views.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>
提前致谢!
答案 0 :(得分: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 Docs的示例:
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']
@LarsVegas
提供的这篇文章In Django 1.4, do Form.has_changed() and Form.changed_data, which are undocumented, work as expected?也很有用答案 1 :(得分:0)
创建一个名为temper_seal
temper_seal = forms.CharField(widget=forms.HiddenInput())
将temper_seal
的初始值设置为client_id
和identifier
的哈希值以及仅为您的服务器所知的随机常量字符串。
当表单返回用户数据时,请散列client_id
和identifier
的值以及之前使用的常量字符串。将此值与隐藏temper_seal
字段中提交的值进行比较。如果它们相同,则用户不会更改client_id
和identifier
中的数据。
答案 2 :(得分: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})