实现验证码控件代码验证控件,方便使用验证码(修改)
网站在进行重要操作步骤时,为了防止攻击,一般都采用生成验证码的方法。为了使用方便,我自己写了一个从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" />
后台编码:<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);
}
}
{
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<double, double> _cacheSqrt = new Dictionary<double, double>();
/// <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(1, 1))
{
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<string, string> ValidateCodeDictionary
{
get
{
if (HttpContext.Current.Session[SESSIONKEY] == null)
{
HttpContext.Current.Session[SESSIONKEY] = new Dictionary<string, string>();
}
return HttpContext.Current.Session[SESSIONKEY] as Dictionary<string, string>;
}
}
}
/// <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;
}
}
}
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<double, double> _cacheSqrt = new Dictionary<double, double>();
/// <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(1, 1))
{
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<string, string> ValidateCodeDictionary
{
get
{
if (HttpContext.Current.Session[SESSIONKEY] == null)
{
HttpContext.Current.Session[SESSIONKEY] = new Dictionary<string, string>();
}
return HttpContext.Current.Session[SESSIONKEY] as Dictionary<string, string>;
}
}
}
/// <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
转载请注明出处。