代码改变世界

ASP.NET中防止表单重复提交

2012-04-24 16:43  我就是我O(∩_∩)O~  阅读(478)  评论(0编辑  收藏  举报

实现方法:
    在页面上放置一个Hidden域,当页面第一次载入的时候,在Session里面保存一个标志,同时,把这个标志保存到页面上的Hidden里面。在提交表单时,判断表单中提交上来的Hidden和Session中的标志是否一致,就可以知道是正常的提交表单,还是刷新页面导致的重复提交。需要注意的是,在每次提交表单的处理之后,要更新Session里面的标志。

页面代码:

<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>

需要注意的地方:
    1 GetSessionToken()函数是为了获得 Session里面保存的标志。
    2 Hidden使用了非服务器控件,这是因为我使用服务器控件,并在后台直接获取Session的标志并赋值给这个Hidden的时候,刷新提交到服务器的 表单中的Hidden的值也发生了改变,猜想是服务器控件的话,表单里面的值是保持同步的,当然,也可能是我用的方法不对,嘎嘎。

后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class FormSubmit2 : 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()))
        {
            Thread.Sleep(5000);
            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,纯粹为了让标志短点儿,当然有一点点安全的意 思,哈哈。

 

此博文从网上转播而来,自己也经过测试,确实很不错,分享给大家