在Web开发中,必须面对的问题就是表单的重复提交问题(这里仅指F5刷新形成的重复提交),.NET中处理这个问题彷佛没有什么好的方法。 在网上搜索获得的解决方法主要有两种,一种是直接让表单按钮失效,从而保证一个用户对于一个表单只能提交一次;另外一种方法,是一次提交后把表单清空,在后台逻辑上进行判断,从而区分是否重复提交。
我的感受,第一种方法,用户体验很差,按钮只能按一次,这种应该是用来防治屡次点击提交按钮形成的重复提交的,没法防止刷新形成的二次提交;第二种,两种重复提交均可以防止,可是表单内容就没了,万一有需求不让内容消失,就费些周折。
因而,本身模仿JSP中Struts的令牌,写了一个防止表单被重复提交的方法,和你们分享。
实现原理:
因为刷新提交表单,实际上提交的就是上一次正常提交的表单,因此咱们只要作一个标志,判断出是新表单仍是上一次的旧表单就能够分辨出是否进行了重复提交操做。
实现方法:
在页面上放置一个Hidden域,当页面第一次载入的时候,在Session里面保存一个标志,同时,把这个标志保存到页面上的Hidden里面。在提交表单时,判断表单中提交上来的Hidden和Session中的标志是否一致,就能够知道是正常的提交表单,仍是刷新页面致使的重复提交。须要注意的是,在每次提交表单的处理以后,要更新Session里面的标志。
代码实例:
代码不多,首先是页面上。html
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <input type="text" id="tbxName" runat="server"/> <input type="text" id="tbxPass" value="" runat="server"/> <asp:Button ID="btnSubmit" runat="server" OnClick="Button1_Click" Text="Button" /> <asp:Label ID="lblMessage" runat="server" Text=""></asp:Label> <input id="hiddenTest" type="hidden" value="<%= GetToken() %>" name="hiddenTestN"/> </div> </form> </body> </html>
须要注意的地方:
1 GetSessionToken()函数是为了得到 Session里面保存的标志。
2 Hidden使用了非服务器控件,这是由于我使用服务器控件,并在后台直接获取Session的标志并赋值给这个Hidden的时候,刷新提交到服务器的 表单中的Hidden的值也发生了改变,猜测是服务器控件的话,表单里面的值是保持同步的,固然,也多是我用的方法不对,嘎嘎。
下面是后台代码:c#
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Security.Cryptography; using System.Text; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //第一次载入的时候,生成一个初始的标志 if (null == Session["Token"]) { SetToken(); } } protected void Button1_Click(object sender, EventArgs e) { if (Request.Form.Get("hiddenTestN").Equals(GetToken())) { lblMessage.ForeColor = System.Drawing.Color.Blue; lblMessage.Text = "正常提交表单"; SetToken();//别忘了最后要更新Session中的标志 } else { lblMessage.ForeColor = System.Drawing.Color.Red; lblMessage.Text = "刷新提交表单"; } } //得到当前Session里保存的标志 public string GetToken() { if (null != Session["Token"]) { return Session["Token"].ToString(); } else { return string.Empty; } } //生成标志,并保存到Session private void SetToken() { Session.Add("Token", UserMd5(Session.SessionID + DateTime.Now.Ticks.ToString())); } //这个函数纯粹是为了让标志稍微短点儿,一堆乱码还特有神秘感,另外,这个UserMd5函数是网上找来的现成儿的 protected string UserMd5(string str1) { string cl1 = str1; string pwd = ""; MD5 md5 = MD5.Create(); // 加密后是一个字节类型的数组 byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1)); // 经过使用循环,将字节类型的数组转换为字符串,此字符串 是常规字符格式化所得 for (int i = 0; i < s.Length; i++) { // 将获得的字符串使用十六进制类型格式。格式后的字符是 小写的字母,若是使用大写(X)则格式后的字符是大写字符 pwd = pwd + s[i].ToString("X"); } return pwd; } }
须要注意的地方:
1 在页面第一次载入的时候要生成标志,之后就不用了。
2 在表单处理的函数的最后,记得要更新标志。
3 标志我选用了当前SessionID加上当前时间毫秒值,这样基本能够避免标志重复,以后进行了一次MD5,纯粹为了让标志短点儿,固然有一点点安全的意思,哈哈。数组
原文转自:http://www.cnblogs.com/binaryworms/articles/2207028.html安全