实现验证码控件代码验证控件,方便使用验证码(修改)

  网站在进行重要操作步骤时,为了防止攻击,一般都采用生成验证码的方法。为了使用方便,我自己写了一个从BaseValidator实现的验证控件,负责给指定的Image控制设置ImageSrc并在验证失败时,清空TextBox控制的值。从BaseValidator继承,是因为服务端只需调用
 if(Page.IsValid){} 
就可以了。

下面主要代码公布如下,希望大家拍砖。
使用代码示例:
                        <asp:TextBox ID="TextBox1" runat="server" AutoCompleteType="Disabled"  ></asp:TextBox>
                        
<asp:Image ID="Image1" runat="server" ImageAlign="absMiddle" />
                        
<asp:ImageValidator runat="server" ID="imagevalidator" 
          ImageControl
="Image1" 
          ControlToValidate
="TextBox1" 
          Display
="Dynamic"
          CharCount
="4" 
          Fonts
="宋体,Gungsuh,仿宋,黑体" 
          BgColor
="White" 
          MaxFontSize
="16" 
          MinFontSizePercent
="50" 
          ErrorMessage
="验证码错误!" 
          SetFocusOnError
="True" />
后台编码:
        protected void OnLogin(object sender, EventArgs e)
        
{
            
try
            
{
                
if (Page.IsValid)
                
{
                    
string hashedPwd = Utility.Md5.HashedString(this.tbLoginPassword.Text.Trim());
                    Manager manager 
= Manager.CreateInstance(this.tbLoginName.Text.Trim(), hashedPwd);
                    
//登陆成功
                    ManagePageBase.SetAuthSession(manager);
                                                          System.Web.Security.FormsAuthentication.RedirectFromLoginPage(manager.Name, 
false);
                }

            }

            
catch (BusinessException ex)
            
{
                
this.ShowMessage(ex.Message);
            }

        }


实现代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Web.Configuration;
using System.Drawing.Design;
using System.Drawing;
using System.Web.SessionState;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace Iyond.Web.UI.WebControls
{
    
public class ImageValidator : System.Web.UI.WebControls.BaseValidator
    
{

        
private string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        [Bindable(
false)]
        [Category(
"Data")]
        [DefaultValue(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")]
        [Localizable(
true)]
        [Description(
"用于生成验证码的源字符")]
        
public string Chars
        
{
            
get
            
{
                
return _chars;
            }


            
set
            
{
                _chars 
= value;
            }

        }


        
private int _charCount = 5;
        [Bindable(
false)]
        [Category(
"Data")]
        [DefaultValue(
5)]
        [Localizable(
true)]
        [Description(
"验证码中字符的数量")]
        
public int CharCount
        
{
            
get
            
{
                
return _charCount;
            }

            
set
            
{
                _charCount 
= value;
            }

        }


        
private string _pageValidateCode = "~/IyondValidateCode.aspx";
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"在Web.config中的HttpHandler节中配置的读取验证码的页面")]
        
public string ValidateCodePage
        
{
            
get return _pageValidateCode; }
            
set { _pageValidateCode = value; }
        }



        
private int _minFontSizePercent = 60;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"字体最小高度占Image控件高度的百分比")]
        
public int MinFontSizePercent
        
{
            
get
            
{
                
return _minFontSizePercent;
            }

            
set
            
{
                
if (value > 100)
                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最大为100(表示100%)");
                
if (value < 50)
                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最小为50(表示50%)");

                _minFontSizePercent 
= value;
            }

        }



        
public int MinFontSize
        
{
            
get
            
{
                
return Convert.ToInt32(this.MaxFontSize * this.MinFontSizePercent / 100 + 1);
            }

        }


        
private int _maxFontSize = 100;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"字体最大高度占Image控件高度的百分比")]
        
public int MaxFontSize
        
{
            
get
            
{
                
return _maxFontSize;
            }

            
set
            
{
                
if (value > 100)
                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最大为100");
                
if (value < 6)
                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最小为6");
                _maxFontSize 
= value;
            }

        }


        
private Color _fontColor = Color.Black;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"字体颜色")]
        
public Color FontColor
        
{
            
get
            
{
                
return _fontColor;
            }

            
set
            
{
                _fontColor 
= value;
            }

        }


        
private Color _bgColor = Color.White;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"字体颜色")]
        
public Color BgColor
        
{
            
get
            
{
                
return _bgColor;
            }

            
set
            
{
                _bgColor 
= value;
            }

        }


        
private bool _ignoreCase = true;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"是否乎略大小写")]
        
public bool IgnoreCase
        
{
            
get return _ignoreCase; }
            
set { _ignoreCase = value; }
        }


        
private bool _enableChangeImage = true;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"是否允许更换图片")]
        
public bool EnableChangeImage
        
{
            
get return _enableChangeImage; }
            
set { _enableChangeImage = value; }
        }


        
private int _maxRotate = 45;
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"每个字的最大旋转角度")]
        
public int MaxRotate
        
{
            
get return _maxRotate; }
            
set { _maxRotate = value; }
        }


        
private List<string> _fonts = new List<string>();
        [Category(
"Data")]
        [Localizable(
true)]
        [Description(
"字体列表,从中随机选择")]
        [Editor(
"System.Windows.Forms.Design.StringArrayEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
        
typeof(UITypeEditor)), TypeConverter(typeof(FontNamesConverter)),
        RefreshProperties(RefreshProperties.Repaint), 
        NotifyParentProperty(
true)]
        
public string[] Fonts
        
{
            
get
            
{
                
return _fonts.ToArray();
            }

            
set
            
{
                
if (value == null)
                    
throw new ArgumentNullException("Fonts");

                _fonts.Clear();
                _fonts.AddRange(value);
            }

        }




        
private static Dictionary<string, ImageValidatorConfig> runtimeConfig = new Dictionary<string, ImageValidatorConfig>();

        
/// <summary>
        
/// 查询验证码配置
        
/// </summary>
        
/// <param name="sign">验证码标识</param>
        
/// <returns></returns>

        public static ImageValidatorConfig GetConfig(string sign)
        
{
            
if (!runtimeConfig.ContainsKey(sign))
                
throw new ArgumentOutOfRangeException("sign", sign);

            
return runtimeConfig[sign] as ImageValidatorConfig;
        }



        
/// <summary>
        
/// 计算是不是合法(验证码是不是正确)
        
/// </summary>
        
/// <returns></returns>

        protected override bool EvaluateIsValid()
        
{
            
bool isValid = false;
            
string text1 = base.GetControlValidationValue(base.ControlToValidate);
            
if ((text1 == null|| (text1.Trim().Length == 0))
            
{
                isValid 
= false;
            }

            
else
            
{
                isValid 
= this.ValidateChar();
            }


            
this.IsValid = isValid;
            
return this.IsValid;


        }


        
/// <summary>
        
/// 查看是不是合法
        
/// </summary>
        
/// <returns></returns>

        private bool ValidateChar()
        
{
            
string validatecode = ValidateCodeHandler.GetAndEmptyValidateCode(this.ValidateSign);
            
if (string.IsNullOrEmpty(validatecode))
            
{
                
return false;
            }

            
else
            
{
                
return string.Compare(validatecode, this.GetControlValidationValue(this.ControlToValidate), this.IgnoreCase) == 0;
            }

        }

        
/// <summary>
        
/// 关联的图片控件ID
        
/// </summary>

        [DescriptionAttribute("BaseValidator_ImageControl"), IDReferenceProperty, TypeConverter(typeof(ImageControlConverter)), Themeable(false), DefaultValue(""), CategoryAttribute("Behavior")]
        
public string ImageControl
        
{
            
get
            
{
                
object obj1 = this.ViewState["ImageControl"];
                
if (obj1 != null)
                
{
                    
return (string)obj1;
                }

                
return string.Empty;
            }

            
set
            
{
                
this.ViewState["ImageControl"= value;
            }

        }


        
protected System.Web.UI.WebControls.Image Image
        
{
            
get 
            
{
                
if (string.IsNullOrEmpty(this.ImageControl))
                    
throw new ArgumentNullException("ImageControl");

                
return this.NamingContainer.FindControl(this.ImageControl) as System.Web.UI.WebControls.Image;
            }

        }


        
protected string ValidateSign
        
{
            
get
            
{
                
if (ViewState["imagevalidate::validatesign"== null)
                
{
                    ViewState[
"imagevalidate::validatesign"= Utility.HashedString(string.Format("{0}::{1}",Page.Request.Url.AbsolutePath,this.UniqueID));
                }


                
return Convert.ToString(ViewState["imagevalidate::validatesign"]);
            }

        }


        
protected override void OnPreRender(EventArgs e)
        
{
            
this.Image.ImageUrl = "#";
            
this.Image.Attributes["onload"= "this.style.display=''";

            
if (this.EnableChangeImage)
            
{
                Image.ToolTip 
= "看不清楚吗?双击换一张";
                Image.Attributes[
"ondblclick"= "if(!this.orgsrc)this.orgsrc=this.src;this.src=this.orgsrc + '&t=' + new Date().valueOf()";
            }

            
this.Image.Style.Add(HtmlTextWriterStyle.Display, "none");
            StringBuilder sbjs 
= new StringBuilder();
            sbjs.AppendFormat(
"javascript:this.onerror=null;this.src='{0}?sign={1}';", Page.ResolveClientUrl(this.ValidateCodePage), this.ValidateSign);

            
this.Image.Attributes.Add("onerror", sbjs.ToString());

            runtimeConfig[
this.ValidateSign] = new ImageValidatorConfig(this.Chars, this.CharCount,this.FontColor, 
                
this.Fonts,this.MinFontSize, this.MaxFontSize);

            
if (!this.IsValid)
            
{
                ITextControl textInput 
= this.NamingContainer.FindControl(this.ControlToValidate) as ITextControl;
                
if (textInput != null)
                
{
                    textInput.Text 
= "";
                }


            }



            
base.OnPreRender(e);
        }

            


    }


    
/// <summary>
    
/// 查找Image控件ID列表
    
/// </summary>

    public class ImageControlConverter : ControlIDConverter
    
{
        
protected override bool FilterControl(Control control)
        
{
            
if (control is System.Web.UI.WebControls.Image)
                
return true;
            
else
            
{
                
return false;
            }

            
        }

    }


    
/// <summary>
    
/// 控制配置类
    
/// </summary>

    public class ImageValidatorConfig
    
{
        
private string _chars = string.Empty;

        
/// <summary>
        
/// 可用字符列表构成的串
        
/// </summary>
        
/// <example>
        
/// 123456789
        
/// </example>

        public string Chars
        
{
            
get
            
{
                
return _chars;
            }


            
set
            
{
                _chars 
= value;
            }

        }


        
private int _charCount = 5;

        
/// <summary>
        
/// 验证图片上字符数量
        
/// </summary>

        public int CharCount
        
{
            
get
            
{
                
return _charCount;
            }

            
set
            
{
                _charCount 
= value;
            }

        }

        
private int _minFontSize = 60;

        
/// <summary>
        
/// 字体最小高度占Image控件高度的百分比
        
/// </summary>

        public int MinFontSize
        
{
            
get
            
{
                
return _minFontSize;
            }

            
set
            
{
                _minFontSize 
= value;
            }

        }

        
private int _maxFontSize = 100;

        
/// <summary>
        
/// 字体最大高度占Image控件高度的百分比
        
/// </summary>

        public int MaxFontSize
        
{
            
get
            
{
                
return _maxFontSize;
            }

            
set
            
{
                _maxFontSize 
= value;
            }

        }


        
private Color _fontColor = Color.Black;

        
/// <summary>
        
/// 字符颜色
        
/// </summary>

        public Color FontColor
        
{
            
get
            
{
                
return _fontColor;
            }

            
set
            
{
                _fontColor 
= value;
            }

        }


        
private Color _bgColor = Color.White;

        
/// <summary>
        
/// 背景颜色
        
/// </summary>

        public Color BgColor
        
{
            
get
            
{
                
return _bgColor;
            }

            
set
            
{
                _bgColor 
= value;
            }

        }


        
private string[] _fonts = null;

        
/// <summary>
        
/// 可用字体列表,生成时,会随机选择
        
/// </summary>

        public string[] Fonts
        
{
            
get
            
{
                
return _fonts;
            }

            
set
            
{
                
if (value == null)
                    
throw new ArgumentNullException("Fonts");

                
if(value.Length == 0)
                
{
                    
throw new ArgumentException("至少指定一种字体");
                }

                _fonts 
= value;
            }

        }


        
private int _maxRotate = 45;

        
/// <summary>
        
/// 每个字符最大旋转角度
        
/// </summary>

        public int MaxRotate
        
{
            
get return _maxRotate; }
            
set { _maxRotate = value; }
        }





        
public ImageValidatorConfig(string chars, int charCount, Color fontColor, string[] fonts, int minFontSise, int maxFontSize)
        
{
            
this.Chars = chars;
            
this.CharCount = charCount;
            
this.FontColor = fontColor;
            
this.MinFontSize = minFontSise;
            
this.MaxFontSize = maxFontSize;
            
this.Fonts = fonts;
        }

    }



    
public class ValidateCodeHandler : System.Web.IHttpHandler, IRequiresSessionState
    
{
        
IHttpHandler 成员

        
protected static string SESSIONKEY = "iyond::imagevalidator";

        
protected static Dictionary<doubledouble> _cacheSqrt = new Dictionary<doubledouble>();

        
/// <summary>
        
/// 为了加快开方,自己写一个开方函数
        
/// </summary>
        
/// <param name="d"></param>
        
/// <returns></returns>

        public static double Sqrt(double d)
        
{
            
if (_cacheSqrt.ContainsKey(d))
                
return _cacheSqrt[d];
            
else
            
{
                
lock (_cacheSqrt)
                
{
                    
double ret = Math.Sqrt(d);
                    _cacheSqrt[d] 
= ret;
                    
return ret;
                }

            }

        }


        
/// <summary>
        
/// 取验证码图片的字串形式,取出时清空。以防止漏洞
        
/// </summary>
        
/// <param name="sign">验证码配置标识</param>
        
/// <returns></returns>

        public static string GetAndEmptyValidateCode(string sign)
        
{
            
if (ValidateCodeDictionary.ContainsKey(sign))
            
{
                
string validatecode = ValidateCodeDictionary[sign];
                ValidateCodeDictionary[sign] 
= string.Empty;
                
return validatecode;
            }

            
else
            
{
                
return string.Empty;
            }

        }



        
/// <summary>
        
/// 依配置生成验证码图片
        
/// </summary>
        
/// <param name="sign">验证码配置标识</param>
        
/// <returns></returns>

        public static System.Drawing.Image BuildValidateImage(string sign)
        
{
            
//得到验证吗生成配置
            ImageValidatorConfig config = ImageValidator.GetConfig(sign);

            
//生成新验证码
            string validatecode = Utility.GetRandomChar(config.Chars, config.CharCount);
            ValidateCodeDictionary[sign] 
= validatecode;

            Random random 
= new Random();

            
//随机生成每个字要使用的字体和大小
            List<DrawCharInfo> draws = new List<DrawCharInfo>();
            
using (Bitmap bmpTemp = new Bitmap(11))
            
{
                
using (Graphics gm = Graphics.FromImage(bmpTemp))
                
{
                    
using (SolidBrush brush = new SolidBrush(config.FontColor))
                    
{
                        
char[] chars = validatecode.ToCharArray();
                        
foreach (char ch in chars)
                        
{
                            
string fontName = config.Fonts[random.Next(0, config.Fonts.Length - 1)];
                            
float fontSize = Convert.ToSingle(random.Next(config.MinFontSize, config.MaxFontSize));
                            Font font 
= new Font(fontName, fontSize , FontStyle.Regular, GraphicsUnit.Pixel);

                            SizeF size 
= gm.MeasureString(ch.ToString(), font);

                            draws.Add(
new DrawCharInfo(ch, font, size));
                        }

                    }

                }

            }


            
//找出最大高度,找出图片宽度
            int bmpWidth = 0, bmpHeight = 0;
            
foreach (DrawCharInfo dci in draws)
            
{
                bmpWidth 
+= Convert.ToInt32(dci.Size.Width) + 1;
                bmpHeight 
= Math.Max(bmpHeight, Convert.ToInt32(dci.Size.Height) + 1);
            }



            
//依每个字符的配置,生成图片
            Bitmap bmp = new Bitmap(bmpWidth, bmpHeight);
            
using (Graphics g = Graphics.FromImage(bmp))
            
{
                g.SmoothingMode 
= System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                
using (SolidBrush brush = new SolidBrush(config.FontColor))
                
{
                    
//用背景清空,将来可以考虑生成背景
                    g.Clear(config.BgColor);

                    
//宽度计数
                    float x = 0;

                    
foreach (DrawCharInfo dci in draws)
                    
{
                        
//保存场景配置
                        GraphicsState gs = g.Save();

                        
//随机Y坐标
                        float y = random.Next(Math.Max(0, bmpHeight - Convert.ToInt32(dci.Size.Height))) / 2;

                        
//随机旋转角度
                        float rotate = random.Next(-config.MaxRotate, config.MaxRotate);

                        
//计算宽高
                        float halfWidth = dci.Size.Width / 2;
                        
float halfHeight = dci.Size.Height / 2;

                        
//变换坐标
                        g.TranslateTransform(x + halfWidth, y + halfHeight);
                        g.RotateTransform(rotate);

                        
//打印字符
                        g.DrawString(dci.Char.ToString(), dci.Font, brush, -halfWidth, -halfHeight);

                        
//原来场景
                        g.Restore(gs);

                        
//增加宽度计数
                        x += dci.Size.Width;
                    }

                }

            }


            
//返回图片
            return bmp;

        }


        
/// <summary>
        
/// 保存每个标识的验证码字串
        
/// </summary>

        protected static Dictionary<stringstring> ValidateCodeDictionary
        
{
            
get
            
{
                
if (HttpContext.Current.Session[SESSIONKEY] == null)
                
{
                    HttpContext.Current.Session[SESSIONKEY] 
= new Dictionary<stringstring>();
                }


                
return HttpContext.Current.Session[SESSIONKEY] as Dictionary<stringstring>;
            }

        }

    }


    
/// <summary>
    
/// 每个字符的在验证吗图片的字体,大小信息
    
/// </summary>

    internal class DrawCharInfo
    
{
        
private char _char;
        
private Font _font;
        
private SizeF _size;


        
/// <summary>
        
/// 字符
        
/// </summary>

        public Char Char
        
{
            
get return _char; }
        }


        
/// <summary>
        
/// 字体
        
/// </summary>

        public Font Font
        
{
            
get return _font; }
        }


        
/// <summary>
        
/// 字体所占区域
        
/// </summary>

        public SizeF Size
        
{
            
get return _size; }
        }


        
public DrawCharInfo(char ch, Font font, SizeF size)
        
{
            
this._char = ch;
            
this._font = font;
            
this._size = size;
        }

    }

}


QQ:273352165 evlon#126.com 转载请注明出处。
原文地址:https://www.cnblogs.com/evlon/p/688695.html