Django框架开发中避免表单重复提交

  Form表单做为web2.0时代的重要角色,也是我们与web网站进行数据交互的重要渠道,但是大家在web网站开发过程中,都会遇到一个问题,那就是如何避免表单重复提交,我们可不确定用户可在提交了一个表单后,是否有足够的耐心等待我们的程序加载完成,如果此时用户不耐烦的在前台重复刷新页面,那么就会造成数据重复提交、信息不准确,因此我们在程序设计时一定要规避这样的问题,接下来介绍一下在Django框架开发中如何避免此问题。

首先说明一下Http协议中两种非常常见的方法GET和POST。

1、GET方法往往被视为向服务器索取信息的一种手段,但是通过使用"?"和"&"符号也可以将不同的表单项提交给服务器,例如"/test?id=1"中我们就将id=1提交给了后台,有时在一些特殊情况中,我们甚至不需要在html中写form表单,只要我们保证url正确就可以了,但是使用GET方式提交也有一个问题需要注意,IE对于URL长度的限制是2083个字节,其他浏览器或是web server都有不同的限制,所以在提交较长的内容时,GET方法就有些不合适了。

2、POST方法相比GET方法在数据提交上更安全一些,因为GET方法将参数统一放到了URL中,随后在HTTP包头中发向服务器,但是提交的参数也就无疑被暴露了,在浏览器中可以直观的看到提交的具体内容,在web server中也可以通过访问日志随便查看提交的内容,对于有安全性的数据一定是采用POST方式来提交的,同时对于密码等敏感内容也一定要做加密处理,采用POST方法对于数据内容理论上也没有长度限制,这样就可以提交更多的数据内容了。

  使用POST方法提交表单往往可以增加信息传输的安全性,如果表单项过多也避免了较长的url,因此在web开发中我更喜欢用POST方法,回到之前的问题,就是页面提交过后,此时如果刷新页面,那么浏览器会提示重新提交表单,此时如果我们点击继续后,那么浏览器就会将之前提交过的内容再次发送至服务器,如果我们在后台没有做限制处理,那么数据就被重复提交了,试想一下如果A用户要转账给B用户,A用户输入转账金额2000元,在表单提交后,后台根据A用户发送的请求在数据库里更新A账户信息,如果此时A用户重复刷新页面,那么后台岂不是要连续的从A用户里扣除2000元增加到B用户中么,虽然现实生活中不可能发生这样的事情,但是这样却很好的说明了表单重复提交的危险性,因此对于POST方法提交表单,我们可以用下面的方式来避免重复提交。

1、URL重定向

  这种方式较为简单,我们可以在用户提交的表单后,在提交页面做一个读秒的倒计时提示,这也是我们在大多数网站上经常见到的,在倒计时结束后,页面被重新定向到上一级页面,或是我们希望被跳转的页面,这样在一定程度上就避免了重复刷新带来的风险,或是在页面提交后直接进行URL重定向,在Django的视图中我们可以使用HttpResponseRedirect来重定向页面。

2、Cookie验证

  上面的方式我们通过页面来进行控制,也就是说提交过后页面url放生了变化,此时用户再次刷新时就不会请求之前提交的页面,除了URL重定向,我们也可以通过cookie中key-value来做进一步限制,首先进入提交页前我们在cookie中写入一个值,在提交过后重置该值,这样后台通过获取cookie中的值就可以做判断了,此时如果用户再次刷新页面时,就可以返回提示说明信息已经提交过,不需要重复提交,在django框架中的代码如下。

# 表单视图
def page(request):
    response = render_to_response(‘post.html‘)
    # 在客户端Cookie中添加Post表单token,避免用户重复提交表单
    response.set_cookie("postToken",value=‘allow‘)
    return response
 
#提交视图
def post(request):
    # 检测Token值,判断用户提交动作是否合法
    if request.COOKIES["postToken"] !=‘allow‘:
        # 不存在合法Token,该表单为重复提交
        return HttpResponse("you can‘t post it again.")
    ‘‘‘
    代码逻辑处理段
    ‘‘‘
    response = render_to_response(‘newPage.html‘)
    # 表单POST提交成功,重置客户端Cookie中存在的Token值,避免重复提交
    response.set_cookie("postToken",value=‘disable‘)
    return response

3、Hidden属性的隐藏域

  上一种方式我们在用户的浏览器中写入了指定的token值,我们也可以在服务器的session会话中写入特定的信息,然后将内容渲染到html页面中表单的隐藏域,用户从页面中是看不到这个隐藏域的,一般有特殊信息提交时会用到,比如这里的重复提交验证,我们就可以用表单的Hidden这个属性,我们将服务器生成的值写入到表单,随用户操作一起提交回服务器,那么如果该值与服务器端匹配,程序继续执行,否则认为重复提交,这里要注意与cookie操作中一样,我们在提交完后,服务器一定要清空session中的值。

# 表单视图
def page(request):
    # 在服务端session中添加key认证,避免用户重复提交表单
    token = allow # 可以采用随机数
    request.session[‘postToken‘] = token
    # 将Token值返回给前台模板
    return render_to_response(‘post.html‘,‘postToken‘:token)
 
#提交视图
def post(request):
    # 检测session中Token值,判断用户提交动作是否合法
    Token = request.session.get(postToken,default=None)
    # 获取用户表单提交的Token值
    userToken = request.POST[‘postToken‘]
    if  userToken !=Token:
        # 不存在合法Token,该表单为重复提交
        return HttpResponse("you can‘t post it again.")
    ‘‘‘
    代码逻辑处理段
    ‘‘‘
    # 表单POST提交成功,重置服务端中存在的Token值,避免重复提交
    del request.session[‘postToken‘]
    return render_to_response(‘newPage.html‘)

4、验证码

  我们可以在表单页中加入验证码,每次提交时服务端来做验证,但是这样的方式又影响了提交操作的便捷度,有得有失。

对于GET的提交方式较为简单,在提交后重新定义url地址就可以了,因为url中没有了参数,也就避免了重复提交,但是为了避免用户重新访问之前的url地址,我们也可以结合上面的方法来对GET方法进行限制。

写在最后

  对于表单重复提交的情况,我们发现往往最容易出现在表单页与提交页URL相同、或是页面提交后依然停留在提交页URL中,在Django框架中,我认为表单页与提交页应该尽量使用不同的URL,不同的视图,这样我们可以更好的避免该问题,例如在提交后我们将URL重定向到表单页,甚至可以在前台使用Ajax异步来提交数据,这样提交动作不会影响到页面变化,用户再次刷新也只能刷新当前的表单页了。相信在web程序开发中一定还有更多种方法来规避表单重复提交的问题,这里所展示的也不一定是最完整准确的,但在web程序开发中我们一定要考虑到类似这样的异常,这才是最重要的。

原创文章首发自阿布的博客,本文地址:http://www.abuve.com/article/17/


时间: 2024-12-25 13:20:45

Django框架开发中避免表单重复提交的相关文章

Struts2中防止表单重复提交

一.防止表单的重复提交 1.在表单中加入<s:token/>标签 2.在动作类中加入token的拦截器<interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="token"></interceptor-ref> 3.增加一个名称为invalid.token的结果视图<result name="

Struts2中解决表单重复提交

3. 表单的重复提交问题 1). 什么是表单的重复提交 > 在不刷新表单页面的前提下:  >> 多次点击提交按钮 >> 已经提交成功, 按 "回退" 之后, 再点击 "提交按钮". >> 在控制器响应页面的形式为转发情况下,若已经提交成功, 然后点击 "刷新(F5)" > 注意: >> 若刷新表单页面, 再提交表单不算重复提交 >> 若使用的是 redirect 的响应类型,

[原创]java WEB学习笔记73:Struts2 学习之路-- strut2中防止表单重复提交

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Struts中防止表单重复提交

Struts内部会经过很多interceptor,只需在struts.xml中配置如下代码就可以防止表单重复提交 <action name="login" class="com.lzw.action.UserAction"> <!-- 配置拦截器进行token拦截 --> <interceptor-ref name="defaultStack"/> <interceptor-ref name="

Java中避免表单重复提交

表单的重复提交: 没有完整的进行一次,先请求表单页面->再提交表单过程而完成数据提交 造成的根本原因: 没有完整的进行一次,先请求表单页面->再提交表单过程. 造成重复提交的现象: 由于服务器缓慢或网络延迟的原因,重复点击提交按钮. 已经提交成功,刷新成功页面(forward)(请求转发). 已经提交成功,通过回退,再次点击提交按钮 注意:回退后,刷新表单页面,重新再提交,这时,不是重复提交,而是发送新的请求,在Firefox下,重复提交到同一个地址的操作无效. 案例: 1 @WebServl

12-struts2防止表单重复提交

防止表单重复提交 问题:什么是表单重复提交? regist.jsp----->RegistServlet 表单重复提交 危害: 刷票. 重复注册.带来服务器访问压力(拒绝服务) 解决方案: 在页面上生成一个令牌(就是一个随机字符串),将其存储到session中,并在表单中携带. 在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题, 将session中令牌删除. struts2中怎样解决表单重复提交: 在struts2中解决表单重复提交,可以使用它定义的一个i

【Struts2】防止表单重复提交

一.概述 二.Struts2中解决方案 三.实现步骤 一.概述 regist.jsp----->RegistServlet 表单重复提交 危害: 刷票. 重复注册.带来服务器访问压力(拒绝服务) 解决方案: 在页面上生成一个令牌(就是一个随机字符串),将其存储到session中,并在表单中携带. 在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题,将session中令牌删除. 二.Struts2中解决方案 struts2中怎样解决表单重复提交: 在strut

SSH框架下的表单重复提交

前几天做了一个功能,是在某个操作后,刷新父页面的,刷新时弹出了下面图的框: 网上查了之后发现这个框是表单重复提交时出现的.分析后发现,这个页面的上一个动作是form submit(在ssh框架下),这时frame.location值是提交表单时的action和method,此时做frame.location.reload(),就又一次做了提交表单的动作.这就是问题的症结.上图中的框是浏览器自己发现表单重复提交而出现的. 这个时候想刷新页面,就要换一个不是提交表单的location值了,问题因此得

JS中如何防止表单重复提交问题

在登录页面html中写如下代码 <script type="text/javascript"> var issubmit=false; function dosubmit(){ if(issubmit==false){ issubmit=true; return true; }else{ return false; } } </script> </head> <body> <form action="/Day07/Form