zoukankan      html  css  js  c++  java
  • 艾伟:较为周全的Asp.net提交验证方案(Session版) 狼人:

    此前我介绍了使用数据库实现的提交验证方案,一些朋友怀疑其效率不佳,认为Session是更好的方案。

    的确使用Session也不会消耗太多内存,而且如今内存白菜价,最不济就随手买个2G的插上也就够了,所以我将在此写下Session版的实现提要,其余细节参考前篇。

    实现方案简述:

    Session中存储一个哈希表用以记录该用户的每一条验证信息,哈希表的键为验证信息的过期时间,值为验证码的明文。

    过期时间使用ViewState存储,以发给客户端,并在提交时获取,以读取对应的验证码明文。

    传给验证码生成页面的ID参数是经ToFileTime()方法转换的过期时间,验证码生成页获取到此参数后进行逆转换,再读取对应的验证码明文以生成显示。

    代码讲解:

    先建立一个静态类,名为“提交验证”,将用于存储验证信息的Session变量封装为一个属性:

    ///

    /// 验证信息表

    ///

    static Hashtable 验证信息

    {

        get

        {

            return Core.函数库.网络.Session["验证信息"] as Hashtable;

        }

        set

        {

            Core.函数库.网络.Session["验证信息"] = value;

        }

    }

    清理方法,用于将过期的数据清除:

    ///

    /// 清理所有过期的验证信息

    ///

    public static void 清理()

    {

        if (验证信息 == null || 验证信息.Count < 5) return;

        foreach (DictionaryEntry f in (Hashtable)验证信息.Clone())

        {

            if ((DateTime)f.Key < DateTime.Now) 验证信息.Remove(f);

        }

    }

    小于5条验证信息则忽略。

    克隆一个验证信息表供foreach使用,如果使用原表循环的话,直接移除内容会改变表长度,从而引发异常。

    添加方法:

    ///

    /// 添加一个新的验证信息。

    ///

    /// 验证码">要保存的验证码

    /// 过期时间差值">用于计算过期时间,单位为分钟

    /// 过期时间戳

    public static DateTime 添加(string 验证码, byte 过期时间差值)

    {

        清理();

        var 过期时间 = DateTime.Now.AddMinutes(过期时间差值);

        if (验证信息 == null) 验证信息 = new Hashtable();

        验证信息.Add(过期时间, 验证码);

        return 过期时间;

    }

    在添加前进行过期信息清理工作。

    获取、验证、移除方法:

    ///

    /// 根据过期时间戳获取对应的验证码

    ///

    /// 过期时间戳">验证信息过期时间戳

    /// 验证码明文

    public static string 获取(DateTime 过期时间戳)

    {

        return 验证信息[过期时间戳] as string;

    }

     

    ///

    /// 验证用户输入的验证码是否正确

    ///

    /// 过期时间戳">验证信息过期时间戳

    /// 验证码">用户输入的验证码

    /// 返回错误信息,如验证成功则返回null

    public static string 验证(DateTime 过期时间戳, string 验证码)

    {

        if (过期时间戳 < DateTime.Now) return "验证信息已过期";

        var 验证码明文 = 获取(过期时间戳);

        if (验证码明文 == null) return "验证信息无效或已过期";

        else if (验证码明文.ToLower() != 验证码.ToLower()) return "验证码错误";

        else return null;

    }

     

    ///

    /// 根据过期时间戳移除对应的验证信息

    ///

    /// 过期时间戳">验证信息过期时间戳

    public static void 移除(DateTime 过期时间戳)

    {

        验证信息.Remove(过期时间戳);

    }

    使用方法:

    使用时在页面上封装一个基于ViewState属性:

    ///

    /// 时间戳属性,基于ViewState

    ///

    public DateTime? 时间戳

    {

        get

        {

            return ViewState["时间戳"] as DateTime?;

        }

        set

        {

            ViewState["时间戳"] = value;

        }

    }

    然后在load事件中调用:

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        {

            时间戳 = 提交验证.添加();

            Image1.ImageUrl = "~/VerifyImage.aspx?ID=" + 时间戳.Value.ToFileTime();

        }

    }

    (无参数的“添加”方法是我实现的一个适配器封装方法,采用默认的过期时间设置,随机生成验证码)

    提交时的调用:

    protected void Button1_Click(object sender, EventArgs e)

    {

        var s = 提交验证.验证(时间戳.Value, TextBox1.Text);

        if (s == null)

        {

            CustomValidator1.IsValid = true;

     

            //提交...

     

            提交验证.移除(时间戳.Value);

        }

        else

        {

            CustomValidator1.IsValid = false;

            CustomValidator1.ErrorMessage = s;

        }

    }

    提示:

    验证码生成时,建议只采用这些字符:2345678abcdefghijkmnprstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

    这里放弃了一些容易产生视觉混淆的字符,比如1Il0Oo,减少用户挠墙、砸电脑的可能。

  • 相关阅读:
    设计模式-状态模式
    设计模式-策略模式
    Spring MVC 梳理
    Spring MVC 梳理
    设计模式-总结
    Spring boot 梳理
    Spring boot 梳理
    [DP题]最长上升子序列
    NOIP2013 Day1
    20171025日程
  • 原文地址:https://www.cnblogs.com/waw/p/2156932.html
Copyright © 2011-2022 走看看