我正在尝试实施服务器端检查,以防止用户双重提交我的表单(Django网络应用)。
我正在尝试的一种技巧是:
1)创建表单时,在会话中保存唯一ID,并将唯一ID值传递给模板。
2)提交表单时,从会话中弹出唯一ID,并将其与从表单中检索到的相同唯一ID进行比较。
3)如果值相同,则允许处理,否则不允许。
以下是我的通用代码的快速浏览:
def my_view(request):
if request.method == 'POST':
secret_key_from_form = request.POST.get('sk','0')
secret_key_from_session = request.session.pop('secret_key','1')
if secret_key_from_form != secret_key_from_session:
return render(request,"404.html",{})
else:
# process the form normally
form = MyForm(request.POST,request.FILES)
if form.is_valid():
# do something
else:
# do something else
else:
f = MyForm()
secret_key = uuid.uuid4()
request.session["secret_key"] = secret_key
request.session.modified = True
return render(request,"my_form.html",{'form':f,'sk':secret_key})
这是一个示例模板:
<form action="{% url 'my_view' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="sk" value="{{ sk }}">
{{ form.my_data }}
<button type="submit">OK</button>
</form>
此设置有失败以停止双重提交。
即,一个人可以继续点击狂热,最终仍然会提交大量的副本。此外,如果我打印secret_key_from_form
和secret_key_from_session
,我会看到它们被多次打印,即使第一次尝试后secret_key_from_session
应该弹出 。
这有什么用?我该如何解决?
UPDATE:当我使用redis缓存来保存特殊键的值时,这种安排非常有效。因此,似乎罪魁祸首是我无法更新request.session
值(即使尝试request.session.modified=True
)。我对可能出现问题的建议持开放态度。
请注意,这个问题专门针对双重提交的服务器端解决方案 - 我的JS措施是独立的,并且是这个问题所独有的。
答案 0 :(得分:0)
您可能只需要request.session.modified = True
。如果您想确保会话正在删除,您也可以使用del。
secret_key_from_session = request.session.get('secret_key','1')
del request.session['secret_key']
request.session.modified = True
答案 1 :(得分:0)
我无法弄清楚导致问题的原因,但通过用Redis
缓存替换每个request.session
来电,我能够得到我想要的结果。我愿意接受建议。