最新发布,验证码控件,绝对原创
这是我历时一个月逐渐完善的验证码控件。有如下特性:1、基于流方式生成图片,突破文件系统局限,并且对每个访问网站的对话隔离,互不影响。
2、采用稳定性较好的ViewState,使用T-DES算法和MachineKey加密敏感数据。
3、可选数字、小写字母、大写字母、100个常用汉字任意搭配。
4、提供一个验证方法(返回布尔),验证方法还可设置是否区分大小写验证。
5、提供划线和打点方式的噪音生成,并可设置强度值。
6、图片背景、字符、噪音均可自行设置颜色。
7、可选生成字符字体(基于服务器已有字体)
8、兼容XHTML标准和完备样式。
9、配备IHttpHandler接口。
10、基本的设计时支持。(但在VS2008 .net3.5下没有成功:(~~)
验证码控件结构如下:
class VerificationCode 验证码控件主体。
enum VerificationCodeImageFormat 枚举验证码控件输出图片的格式。gif或jpg
enum VerificationCodeNoiseRenderMode 枚举验证码噪音渲染模式,是在字符底层渲染还是在字符上层渲染。
enum VerificationCodeNoiseType 枚举验证码渲染类型,点或直线。
class VCodeTransferFormatter 用于将验证码对象信息格式化传输的格式器
class VerificationCodeDesigner 对验证码控件提供设计时支持
class TDesEncrpytor 封装一个TDES加密解密器
class TDesDecryptException 捕捉加密解密异常,从Exception简单继承。
代码公布如下:
程序代码:
using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Drawing.Design; using System.Drawing; using System.Collections; using System.Web.Security; using System.Drawing.Imaging; using System.Reflection; using System.Security.Cryptography; using System.Drawing.Text; namespace BlogLan.Web.Controls { /// <summary> /// 验证码控件。 /// </summary> [DefaultProperty("CodeLength")] [ToolboxData("<{0}:VerificationCode runat=server></{0}:VerificationCode>")] [DesignerAttribute(typeof(Designer.VerificationCodeDesigner))] [Description("验证码控件。")] public class VerificationCode : WebControl, IHttpHandler { private Random rand; /// <summary> /// 表示数字字符集。 /// </summary> public static char[] NumericCharset = new char[] { '2', '3', '4', '5', '6', '7' }; /// <summary> /// 表示大写英文字母字符集。 /// </summary> public static char[] UppercaseCharset = new char[] { 'A', 'B', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'Q', 'R', 'T', 'W', 'X', 'Y' }; /// <summary> /// 表示小写英文字母字符集。 /// </summary> public static char[] LowercaseCharset = new char[] { 'a', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'r', 't', 'u', 'w', 'x', 'y' }; /// <summary> /// 表示100个最常用简体中文汉字字符集。 /// </summary> public static char[] ChineseCharset = new char[]{'的','一','是','在','不','了','有','和','人','这', '中','大','为','上','个','国','我','以','要','他', '时','来','用','们','生','到','作','地','于','出', '就','分','对','成','会','可','主','发','年','动', '同','工','也','能','下','过','子','说','产','种', '面','而','方','后','多','定','行','学','法','所', '民','得','经','十','三','之','进','着','等','部', '度','家','电','力','里','如','水','化','高','自', '二','理','起','小','物','现','实','加','量','都', '两','体','制','机','当','使','点','从','业','本'}; /// <summary> /// 默认构造函数。 /// </summary> public VerificationCode() : base(HtmlTextWriterTag.Img) { rand = new Random(unchecked((int)DateTime.Now.Ticks)); } private byte[] GetMachineKey() { try { object machineKeyConfig = HttpContext.Current.GetSection("system.web/machineKey"); Type machineKeyType = machineKeyConfig.GetType().Assembly.GetType("System.Web.Configuration.MachineKey"); //得到System.Web.Configuration.MachineKey类型 BindingFlags bf = BindingFlags.NonPublic | BindingFlags.Static; //设置绑定标志 MethodInfo byteArrayToHexString = machineKeyType.GetMethod("ByteArrayToHexString", bf); SymmetricAlgorithm algorithm = (SymmetricAlgorithm)machineKeyType.GetField("s_oDes", bf).GetValue(machineKeyConfig); Byte[] decryptionKey = algorithm.Key; return decryptionKey; } catch { return new byte[]{77,236,150,65,103,91,220,81, 49,37,48,208,73,85,150,250, 131,25,228,234,2,155,26,167}; } } /// <summary> /// 获取或设置生成的验证字符个数。 /// </summary> [DefaultValue(4)] [Bindable(true)] [Description("获取或设置生成的验证字符个数。")] public int CodeLength { get { if (this.ViewState["CodeLength"] != null) { return (int)this.ViewState["CodeLength"]; } return 4; } set { this.ViewState["CodeLength"] = value; } } /// <summary> /// 获取或设置生成的缩略图的图片格式。 /// </summary> [Bindable(false)] [DefaultValue(VerificationCodeImageFormat.Gif)] [Description("获取或设置生成的缩略图的图片格式。")] public VerificationCodeImageFormat ImageFormat { get { if (this.ViewState["ImageFormat"] != null) { return (VerificationCodeImageFormat)this.ViewState["ImageFormat"]; } return VerificationCodeImageFormat.Gif; } set { this.ViewState["ImageFormat"] = value; } } /// <summary> /// 获取或设置进行验证时是否区分大小写。 /// </summary> [Bindable(false)] [DefaultValue(false)] [Description("获取或设置进行验证时是否区分大小写。")] public bool CaseSensitive { get { if (this.ViewState["CaseSensitive"] != null) { return (bool)this.ViewState["CaseSensitive"]; } return false; } set { this.ViewState["CaseSensitive"] = value; } } /// <summary> /// 获取或设置图片背景色。 /// </summary> [DefaultValue(typeof(Color), "Black"), Description("获取或设置图片背景色。")] public override Color BackColor { get { if (!base.BackColor.IsEmpty) return base.BackColor; return Color.Black; } set { base.BackColor = value; } } /// <summary> /// 获取或设置前景颜色,通常就是图片上显示的文字颜色。 /// </summary> [DefaultValue(typeof(Color), "White"), Description("获取或设置前景颜色,通常就是图片上显示的文字颜色。")] public override Color ForeColor { get { if (!base.ForeColor.IsEmpty) return base.ForeColor; return Color.White; } set { base.ForeColor = value; } } /// <summary> /// 获取或设置Jpeg图片质量。数值在10-100之间。 /// </summary> [DefaultValue(80), Description("获取或设置Jpeg图片质量。数值在10-100之间。")] public int JpegQualityPercentage { get { if (this.ViewState["JpegQualityPercentage"] != null) { int jqp = (int)this.ViewState["JpegQualityPercentage"]; if (jqp > 100) return 100; if (jqp < 10) return 10; return jqp; } return 80; } set { this.ViewState["JpegQualityPercentage"] = value; } } /// <summary> /// 获取或设置图像噪音干扰的颜色。 /// </summary> [DefaultValue(typeof(Color), "White"), Description("获取或设置图像噪音干扰的颜色。")] public Color NoiseColor { get { if (this.ViewState["NoiseColor"] != null) { return (Color)this.ViewState["NoiseColor"]; } return Color.White; } set { this.ViewState["NoiseColor"] = value; } } /// <summary> /// 获取或设置噪音渲染位置。 /// </summary> [DefaultValue(VerificationCodeNoiseRenderMode.Back), Description("获取或设置噪音渲染位置。")] public VerificationCodeNoiseRenderMode NoiseRenderMode { get { if (this.ViewState["NoiseRenderMode"] != null) { return (VerificationCodeNoiseRenderMode)this.ViewState["NoiseRenderMode"]; } return VerificationCodeNoiseRenderMode.Back; } set { this.ViewState["NoiseRenderMode"] = value; } } /// <summary> /// 获取或设置噪音类型。 /// </summary> [DefaultValue(VerificationCodeNoiseType.Spot), Description("获取或设置噪音类型。")] public VerificationCodeNoiseType NoiseType { get { if (this.ViewState["NoiseType"] != null) { return (VerificationCodeNoiseType)this.ViewState["NoiseType"]; } return VerificationCodeNoiseType.Spot; } set { this.ViewState["NoiseType"] = value; } } /// <summary> /// 获取或设置噪音渲染强度。值范围是0-100,如果设置为0,则不进行噪音渲染。 /// </summary> [DefaultValue(0), Description("获取或设置噪音渲染强度。值范围是0-100,如果设置为0,则不进行噪音渲染。")] public int NoiseRendingIntensity { get { if (this.ViewState["NoiseRendingIntensity"] != null) { int nri = (int)this.ViewState["NoiseRendingIntensity"]; if (nri < 0) return 0; if (nri > 100) return 100; return nri; } return 0; } set { this.ViewState["NoiseRendingIntensity"] = value; } } /// <summary> /// 获取设计时生成的HTML语句。 /// </summary> /// <param name="writer">要写入HTML语句的HtmlTextWriter。</param> protected internal void GetDesignTimeCode(HtmlTextWriter writer) { string ErrorMsg = string.Empty; try { char[] charset = this.CreateUsedCharset(); string OCode = this.GenerateCodeValue(charset, this.CodeLength); this.EncryptCodeValue(OCode); } catch (Exception ex) { this.EncryptCodeValue(string.Empty); ErrorMsg = ex.Message; //return; } Bitmap bmp = this.GetVerificationCodeImage(); string tempUrl = Path.GetTempPath(); if (tempUrl == string.Empty) tempUrl = "C:\\"; tempUrl += Guid.NewGuid().ToString(); if (this.ImageFormat == VerificationCodeImageFormat.Gif) { tempUrl += ".gif"; bmp.Save(tempUrl, System.Drawing.Imaging.ImageFormat.Gif); } else if (this.ImageFormat == VerificationCodeImageFormat.Jpeg) { tempUrl += ".jpg"; bmp.Save(tempUrl, System.Drawing.Imaging.ImageFormat.Jpeg); } this.AddVCodeAttributes(writer, tempUrl); writer.RenderBeginTag(HtmlTextWriterTag.Img); writer.RenderEndTag(); writer.Write(ErrorMsg); //writer.Write("<img src=\"" + tempUrl + "\" />"); } /// <summary> /// 添加VerificationCode属性到HTML标记中。 /// </summary> /// <param name="writer">要写入属性的HtmlTextWriter。</param> /// <param name="ImageUrl">图片的Url路径。</param> protected internal void AddVCodeAttributes(HtmlTextWriter writer, string ImageUrl) { base.AddAttributesToRender(writer); string imageUrl = ImageUrl; if (!this.UrlResolved) { imageUrl = base.ResolveClientUrl(imageUrl); } writer.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl); imageUrl = this.DescriptionUrl; if (imageUrl.Length != 0) { writer.AddAttribute(HtmlTextWriterAttribute.Longdesc, base.ResolveClientUrl(imageUrl)); } imageUrl = this.AlternateText; if ((imageUrl.Length > 0) || this.GenerateEmptyAlternateText) { writer.AddAttribute(HtmlTextWriterAttribute.Alt, imageUrl); } switch (this.ImageAlign) { case ImageAlign.Left: writer.AddAttribute(HtmlTextWriterAttribute.Align, "left"); break; case ImageAlign.Right: writer.AddAttribute(HtmlTextWriterAttribute.Align, "right"); break; case ImageAlign.Baseline: writer.AddAttribute(HtmlTextWriterAttribute.Align, "baseline"); break; case ImageAlign.Top: writer.AddAttribute(HtmlTextWriterAttribute.Align, "top"); break; case ImageAlign.Middle: writer.AddAttribute(HtmlTextWriterAttribute.Align, "middle"); break; case ImageAlign.Bottom: writer.AddAttribute(HtmlTextWriterAttribute.Align, "bottom"); break; case ImageAlign.AbsBottom: writer.AddAttribute(HtmlTextWriterAttribute.Align, "absbottom"); break; case ImageAlign.AbsMiddle: writer.AddAttribute(HtmlTextWriterAttribute.Align, "absmiddle"); break; case ImageAlign.NotSet: break; default: writer.AddAttribute(HtmlTextWriterAttribute.Align, "texttop"); break; } if (this.BorderWidth.IsEmpty) { writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0px"); } } /// <summary> /// 将需要为控件呈现的 HTML 属性和样式添加到指定的 HtmlTextWriter 对象。这通常由系统调用,可以在派生类中重写。 /// </summary> /// <param name="writer">表示要在客户端呈现 HTML 内容的输出流。</param> protected override void AddAttributesToRender(HtmlTextWriter writer) { if (string.IsNullOrEmpty(this.Page.Request["vrfc"])) { VCodeTransferFormatter formatter = new VCodeTransferFormatter(); string querystr = formatter.SerializeFromVCodeControl(this); string imageUrl = this.Page.Request.Url.AbsolutePath + "?vrfc=" + querystr; this.AddVCodeAttributes(writer, imageUrl); } } /// <summary> /// 将控件的内容呈现到指定的编写器中。此方法主要由控件开发人员使用。 /// </summary> /// <param name="writer">表示要在客户端呈现 HTML 内容的输出流。</param> protected override void RenderContents(HtmlTextWriter writer) { } private bool urlResolved; internal bool UrlResolved { get { return this.urlResolved; } set { this.urlResolved = value; } } /// <summary> /// 如无法显示图片时显示的替代文本。 /// </summary> [DefaultValue("Virtual Verification"), Bindable(true), Localizable(true), Description("如无法显示图片时显示的替代文本。")] public virtual string AlternateText { get { if (this.ViewState["AlternateText"] != null) { return (string)this.ViewState["AlternateText"]; } return "Virtual Verification"; } set { this.ViewState["AlternateText"] = value; } } /// <summary> /// 获取或设置一个值,该值指示控件是否生成空字符串值的替换文字属性。 /// </summary> [DefaultValue(true), Description("获取或设置一个值,该值指示控件是否生成空字符串值的替换文字属性。")] public virtual bool GenerateEmptyAlternateText { get { if (this.ViewState["GenerateEmptyAlternateText"] != null) { return (bool)this.ViewState["GenerateEmptyAlternateText"]; } return true; } set { this.ViewState["GenerateEmptyAlternateText"] = value; } } /// <summary> /// 获取或设置图像详细说明的位置。 /// </summary> [Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), UrlProperty, DefaultValue(""), Description("获取或设置图像详细说明的位置。")] public virtual string DescriptionUrl { get { string str = (string)this.ViewState["DescriptionUrl"]; if (str != null) { return str; } return string.Empty; } set { this.ViewState["DescriptionUrl"] = value; } } /// <summary> /// 获取或设置控件相对于网页上其他元素的对齐方式。 /// </summary> [DefaultValue(ImageAlign.NotSet), Description("获取或设置控件相对于网页上其他元素的对齐方式。")] public virtual ImageAlign ImageAlign { get { object obj2 = this.ViewState["ImageAlign"]; if (obj2 != null) { return (ImageAlign)obj2; } return ImageAlign.NotSet; } set { if ((value < ImageAlign.NotSet) || (value > ImageAlign.TextTop)) { throw new ArgumentOutOfRangeException("value"); } this.ViewState["ImageAlign"] = value; } } /// <summary> /// [禁用Enabled属性在任何位置编辑。] /// </summary> [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override bool Enabled { get { return base.Enabled; } set { base.Enabled = value; } } /// <summary> /// [禁用Width属性在任何位置编辑。] /// </summary> [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Unit Width { get { return Unit.Empty; } } /// <summary> /// [禁用Height属性在任何位置编辑。] /// </summary> [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Unit Height { get { return Unit.Empty; } } /// <summary> /// 获取或设置是否允许采用数字字符集。 /// </summary> [DefaultValue(true), Description("获取或设置是否允许采用数字字符集。")] public bool EnableNumericCharset { get { if (this.ViewState["EnableNumericCharset"] != null) { return (bool)this.ViewState["EnableNumericCharset"]; } return true; } set { this.ViewState["EnableNumericCharset"] = value; } } /// <summary> /// 获取或设置是否允许采用小写英文字母字符集。 /// </summary> [DefaultValue(false), Description("获取或设置是否允许采用小写英文字母字符集。")] public bool EnableLowercaseCharset { get { if (this.ViewState["EnableLowercaseCharset"] != null) { return (bool)this.ViewState["EnableLowercaseCharset"]; } return false; } set { this.ViewState["EnableLowercaseCharset"] = value; } } /// <summary> /// 获取或设置是否允许采用大写英文字母字符集。 /// </summary> [DefaultValue(false), Description("获取或设置是否允许采用大写英文字母字符集。")] public bool EnableUppercaseCharset { get { if (this.ViewState["EnableUppercaseCharset"] != null) { return (bool)this.ViewState["EnableUppercaseCharset"]; } return false; } set { this.ViewState["EnableUppercaseCharset"] = value; } } /// <summary> /// 获取或设置是否允许采用简体中文字符集。 /// </summary> [DefaultValue(false), Description("获取或设置是否允许采用简体中文字符集。")] public bool EnableChineseCharset { get { if (this.ViewState["EnableChineseCharset"] != null) { return (bool)this.ViewState["EnableChineseCharset"]; } return false; } set { this.ViewState["EnableChineseCharset"] = value; } } /// <summary> /// 获取或设置自定义字符集。 /// </summary> [DefaultValue(""), Description("获取或设置自定义字符集。")] public string CustomCharset { get { if (this.ViewState["CustomCharset"] != null) { return (string)this.ViewState["CustomCharset"]; } return string.Empty; } set { this.ViewState["CustomCharset"] = value; } } /// <summary> /// 验证输入字符串是否符合图片所示要求。根据CaseSensitive规定是否区分大小写。 /// </summary> /// <param name="Input">输入待验证的字符串。</param> /// <returns>如果验证符合要求,则返回true,否则返回false。</returns> public bool VerifyInput(string Input) { bool flg = false; if (this.CaseSensitive) { flg = this.MD5Code == System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Input, "md5"); if (string.IsNullOrEmpty(this.Page.Request["vrfc"])) { //生成新的验证码。 try { char[] charset = this.CreateUsedCharset(); string OCode = this.GenerateCodeValue(charset, this.CodeLength); this.EncryptCodeValue(OCode); } catch { return false; } } } else { flg = this.MD5Code == System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Input.ToLower(), "md5"); if (string.IsNullOrEmpty(this.Page.Request["vrfc"])) { //生成新的验证码。 try { char[] charset = this.CreateUsedCharset(); string OCode = this.GenerateCodeValue(charset, this.CodeLength); this.EncryptCodeValue(OCode); } catch { return false; } } } return flg; } /// <summary> /// 验证指定的字符串包含控件所含字符串是否符合图片所示要求。根据CaseSensitive规定是否区分大小写。 /// </summary> /// <param name="TextControl">实现ITextControl接口的字符串输入控件。</param> /// <returns>如果验证符合要求,则返回true,否则返回false。</returns> public bool VerifyInput(ITextControl TextControl) { return this.VerifyInput(TextControl.Text); } /// <summary> /// 引发Init事件。 /// </summary> /// <param name="e">包含事件数据的EventArgs对象。</param> protected override void OnInit(EventArgs e) { base.OnInit(e); this.Init += new EventHandler(VerificationCode_Init); this.PreRender += new EventHandler(VerificationCode_PreRender); } /// <summary> /// 引发 PreRender 事件。 /// </summary> /// <param name="e">包含事件数据的 EventArgs 对象。</param> protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (!(this.Page.IsPostBack) && string.IsNullOrEmpty(this.Page.Request["vrfc"])) { //生成新的验证码。 try { char[] charset = this.CreateUsedCharset(); string OCode = this.GenerateCodeValue(charset, this.CodeLength); this.EncryptCodeValue(OCode); } catch { this.EncryptCodeValue(string.Empty); } } } void VerificationCode_PreRender(object sender, EventArgs e) { if (HttpContext.Current != null) { RenderCodeImage(this.Page.Request, this.Page.Response); } } void VerificationCode_Init(object sender, EventArgs e) { if (HttpContext.Current != null) { RenderCodeImage(this.Page.Request, this.Page.Response); } } static void RenderCodeImage(HttpRequest request, HttpResponse response) { if (request["vrfc"] == null) { return; } VerificationCode verCode; try { verCode = new VCodeTransferFormatter().DeserializeToVCodeControl(request["vrfc"]); } catch { verCode = null; } Bitmap bmp; if (verCode != null) { bmp = verCode.GetVerificationCodeImage(verCode); } else { bmp = Properties.Resources.GenerateImageError; } response.Clear(); try { if (verCode.ImageFormat == VerificationCodeImageFormat.Gif) { response.ContentType = "image/gif"; bmp.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); } else if (verCode.ImageFormat == VerificationCodeImageFormat.Jpeg) { response.ContentType = "image/jpeg"; System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters(); long[] quality = new long[] { Convert.ToInt64(verCode.JpegQualityPercentage) }; System.Drawing.Imaging.EncoderParameter encoderParam = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); encoderParams.Param[0] = encoderParam; System.Drawing.Imaging.ImageCodecInfo[] arrayICI = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders(); System.Drawing.Imaging.ImageCodecInfo jpegICI = null; for (int fwd = 0; fwd < arrayICI.Length - 1; fwd++) { if (arrayICI[fwd].FormatDescription.Equals("JPEG")) { jpegICI = arrayICI[fwd]; break; } } if (jpegICI != null) { bmp.Save(response.OutputStream, jpegICI, encoderParams); } else { bmp.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); } } } catch { bmp = Properties.Resources.GenerateImageError; response.ContentType = "image/gif"; bmp.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); } response.End(); } /// <summary> /// 依据当前验证码对象获取验证码图片。 /// </summary> /// <returns>返回图片Bitmap对象。</returns> public Bitmap GetVerificationCodeImage() { return this.GetVerificationCodeImage(this); } /// <summary> /// 依据验证码对象获取验证码图片。 /// </summary> /// <param name="verCode">验证码对象。</param> /// <returns>返回图片Bitmap对象。</returns> private Bitmap GetVerificationCodeImage(VerificationCode verCode) { try { if (verCode == null) { return Properties.Resources.GenerateImageError; } Bitmap tempBmp = new Bitmap(10, 10); Graphics tg = Graphics.FromImage(tempBmp); TDesEncrpytor tdes = new TDesEncrpytor(verCode.GetMachineKey(), new byte[] { 26, 63, 208, 93, 203, 218, 71, 142 }); string OCode = string.Empty; try { OCode = tdes.DecryptFromBase64String(verCode.EncryptedCode); } catch { return Properties.Resources.GenerateImageError; } if (OCode == string.Empty) return Properties.Resources.GenerateImageError; if (verCode.Font.Size.IsEmpty || verCode.Font.Size.Type != FontSize.AsUnit) { verCode.Font.Size = FontUnit.Parse("18px"); } SizeF stringRectg = tg.MeasureString(OCode, new Font(verCode.Font.Name, Convert.ToSingle(verCode.Font.Size.Unit.Value), GraphicsUnit.Pixel)); tg.Dispose(); tempBmp.Dispose(); Bitmap bmp = new Bitmap(Convert.ToInt32(stringRectg.Width), Convert.ToInt32(stringRectg.Height)); Graphics g = Graphics.FromImage(bmp); = System.Drawing. = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; g.Clear(verCode.BackColor); //绘制背景噪音。 if (verCode.NoiseRenderMode == VerificationCodeNoiseRenderMode.Back && verCode.NoiseRendingIntensity != 0) this.RenderNoise(g, verCode, bmp.Size, new Pen(verCode.NoiseColor), verCode.NoiseRendingIntensity); g.DrawString(OCode, new Font(verCode.Font.Name, Convert.ToSingle(verCode.Font.Size.Unit.Value), GraphicsUnit.Pixel), new SolidBrush(verCode.ForeColor), 0f, 0f); //绘制前景噪音。 if (verCode.NoiseRenderMode == VerificationCodeNoiseRenderMode.Front && verCode.NoiseRendingIntensity != 0) this.RenderNoise(g, verCode, bmp.Size, new Pen(verCode.NoiseColor), verCode.NoiseRendingIntensity); g.Dispose(); return bmp; } catch { return Properties.Resources.GenerateImageError; } } /// <summary> /// 渲染噪音。 /// </summary> /// <param name="g">渲染要使用的Graphics对象。</param> /// <param name="vCode">VerificationCode对象。</param> /// <param name="size">画布大小。</param> /// <param name="pen">渲染所使用的Pen对象。</param> /// <param name="Repeat">渲染单元重复基数。根据此基数和其他参数确定渲染的循环次数。</param> protected virtual void RenderNoise(Graphics g, VerificationCode vCode, Size size, Pen pen, int Repeat) { int width = size.Width; int height = size.Height; int repeatCount; if (vCode.NoiseType == VerificationCodeNoiseType.Spot) { repeatCount = Convert.ToInt32((width * height / 250) * Repeat); } else if (vCode.NoiseType == VerificationCodeNoiseType.Line) { repeatCount = Convert.ToInt32((width * height / 1500) * Repeat); } else { repeatCount = 10; } while (repeatCount-- != 0) { int sptX = this.rand.Next(width); int sptY = this.rand.Next(height); int sptX2 = this.rand.Next(width); int sptY2 = this.rand.Next(height); int sptX3 = this.rand.Next(360); int sptY3 = this.rand.Next(360); if (vCode.NoiseType == VerificationCodeNoiseType.Spot) { g.DrawRectangle(pen, (float)sptX, (float)sptY, 0.5f, 0.5f); } else if (vCode.NoiseType == VerificationCodeNoiseType.Line) { g.DrawLine(pen, sptX, sptY, sptX2, sptY2); } else { return; } } } internal string EncryptedCode { get { if (this.ViewState["EncryptedCode"] != null) { return (string)this.ViewState["EncryptedCode"]; } return string.Empty; } set { this.ViewState["EncryptedCode"] = value; } } internal string MD5Code { get { if (this.ViewState["MD5Code"] != null) { return (string)this.ViewState["MD5Code"]; } return string.Empty; } set { this.ViewState["MD5Code"] = value; } } private char[] CreateUsedCharset() { if (!this.EnableNumericCharset && !this.EnableLowercaseCharset && !this.EnableUppercaseCharset && !this.EnableChineseCharset && this.CustomCharset == string.Empty) { throw new EmptyCharsetException("No Charset is Specified"); } ArrayList array = new ArrayList(); if (this.EnableNumericCharset) array.AddRange(VerificationCode.NumericCharset); if (this.EnableLowercaseCharset) array.AddRange(VerificationCode.LowercaseCharset); if (this.EnableUppercaseCharset) array.AddRange(VerificationCode.UppercaseCharset); if (this.EnableChineseCharset) array.AddRange(VerificationCode.ChineseCharset); array.AddRange(this.CustomCharset.ToCharArray()); return (char[])array.ToArray(typeof(char)); } private string GenerateCodeValue(char[] Charset, int CodeLength) { string genstr = string.Empty; if (CodeLength < 1) { throw new CodeLengthException("CodeLength必须是大于1的值。"); } if (CodeLength > 30) { throw new CodeLengthException("CodeLength过长,必须小于30。"); } for (int i = 0; i < CodeLength; i++) { genstr += Charset[this.rand.Next(Charset.Length)].ToString(); } return genstr; } private void EncryptCodeValue(string OriginalValue) { TDesEncrpytor tdes = new TDesEncrpytor(this.GetMachineKey(), new byte[] { 26, 63, 208, 93, 203, 218, 71, 142 }); this.EncryptedCode = tdes.EncryptToBase64String(OriginalValue); if (this.CaseSensitive) { this.MD5Code = FormsAuthentication.HashPasswordForStoringInConfigFile(OriginalValue, "md5"); } else { this.MD5Code = FormsAuthentication.HashPasswordForStoringInConfigFile(OriginalValue.ToLower(), "md5"); } } #region IHttpHandler 成员 /// <summary> /// 获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。 /// </summary> public bool IsReusable { get { return false; } } /// <summary> /// 通过实现 IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。 /// </summary> /// <param name="context">HttpContext 对象,它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session 和 Server)的引用。</param> public void ProcessRequest(HttpContext context) { RenderCodeImage(context.Request, context.Response); } #endregion /// <summary> /// 创建一个新的 ControlCollection 对象来保存服务器控件的子控件(包括文本控件和服务器控件)。 /// </summary> /// <returns>包含当前服务器控件的子服务器控件的 ControlCollection 对象。</returns> protected override ControlCollection CreateControlCollection() { return new EmptyControlCollection(this); } /// <summary> /// 重新更换验证码图片上的字符。 /// </summary> public void ChangeCode() { try { char[] charset = this.CreateUsedCharset(); string OCode = this.GenerateCodeValue(charset, this.CodeLength); this.EncryptCodeValue(OCode); } catch { } } } }
程序代码:
using System; using System.Collections.Generic; using System.Text; namespace BlogLan.Web.Controls { /// <summary> /// 验证码图片格式。 /// </summary> public enum VerificationCodeImageFormat { Gif, Jpeg } }
程序代码:
using System; using System.Collections.Generic; using System.Text; namespace BlogLan.Web.Controls { /// <summary> /// 表示噪音渲染的位置模式。 /// </summary> public enum VerificationCodeNoiseRenderMode { /// <summary> /// 噪音在背景上渲染。 /// </summary> Back, /// <summary> /// 噪音在文字前方渲染。 /// </summary> Front } }
程序代码:
using System; using System.Collections.Generic; using System.Text; namespace BlogLan.Web.Controls { /// <summary> /// 噪音类型。 /// </summary> public enum VerificationCodeNoiseType { /// <summary> /// 点 /// </summary> Spot, /// <summary> /// 线 /// </summary> Line } }
程序代码:
using System; using System.Collections.Generic; using System.Text; using System.Collections; using System.Web.UI; using System.Drawing; using System.Web.UI.WebControls; namespace BlogLan.Web.Controls { /// <summary> /// 表示为了通过字符串传递VerificationCode对象部分值的格式化提供器。 /// </summary> class VCodeTransferFormatter { /// <summary> /// 从VerificationCode对象将有关变量序列化为Los字符串序列。 /// </summary> /// <param name="VCode">要序列化的VerificationCode对象。</param> /// <returns>返回序列化后的字符串。如果输入VerificationCode对象为null,则返回空字符串。</returns> public string SerializeFromVCodeControl(VerificationCode VCode) { if (VCode == null) return string.Empty; ArrayList al = new ArrayList(); //要序列化的值。必须和逆序列化排序一致。 al.Add(VCode.EncryptedCode); al.Add(VCode.BackColor); al.Add(VCode.ForeColor); al.Add(VCode.ImageFormat); al.Add(VCode.JpegQualityPercentage); al.Add(VCode.Font.Name); al.Add(VCode.Font.Size); al.Add(VCode.NoiseColor); al.Add(VCode.NoiseRenderMode); al.Add(VCode.NoiseType); al.Add(VCode.NoiseRendingIntensity); LosFormatter los = new LosFormatter(); StringWriter writer = new StringWriter(); los.Serialize(writer, al); string str = writer.ToString(); writer.Close(); return str; } /// <summary> /// 从输入字符串逆序列化并装配成VerificationCode对象。 /// </summary> /// <param name="Input">由SerializeFromVCodeControl方法序列化并传递的字符串。</param> /// <returns>返回VerificationCode对象。如果逆序列化不成功,将返回null。</returns> public VerificationCode DeserializeToVCodeControl(string Input) { LosFormatter los = new LosFormatter(); ArrayList al = (ArrayList)los.Deserialize(Input); VerificationCode vCode = new VerificationCode(); //逆序列化。顺序必须与序列化时相同。 vCode.EncryptedCode = (string)al[0]; vCode.BackColor = (Color)al[1]; vCode.ForeColor = (Color)al[2]; vCode.ImageFormat = (VerificationCodeImageFormat)al[3]; vCode.JpegQualityPercentage = (int)al[4]; vCode.Font.Name = (string)al[5]; vCode.Font.Size = (FontUnit)al[6]; vCode.NoiseColor = (Color)al[7]; vCode.NoiseRenderMode = (VerificationCodeNoiseRenderMode)al[8]; vCode.NoiseType = (VerificationCodeNoiseType)al[9]; vCode.NoiseRendingIntensity = (int)al[10]; return vCode; } } }
程序代码:
using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; using BlogLan.Web.Controls { class TDesEncrpytor { /// <summary> /// 用随机生成的Key和IV初始化TDes加密器。 /// </summary> public TDesEncrpytor() { this.CreateRandomCodon(); } /// <summary> /// 用随机生成的Key和指定的IV初始化TDes加密器。 /// </summary> /// <param name="IV">指定的IV字节数组,必须符合IVSize指定的长度,否则无效。</param> public TDesEncrpytor(byte[] IV) { this.CreateRandomCodon(); if (IV.Length == IVSize) this.TDesIV = IV; } /// <summary> /// 使用指定的Key和IV初始化TDes加密器。 /// </summary> /// <param name="Key">指定的Key字节数组,必须符合KeySize指定的长度,否则无效。</param> /// <param name="IV">指定的IV字节数组,必须符合IVSize指定的长度,否则无效。</param> public TDesEncrpytor(byte[] Key, byte[] IV) { this.CreateRandomCodon(); if (Key.Length == KeySize) this.TDesKey = Key; if (IV.Length == IVSize) this.TDesIV = IV; } private byte[] tDesKey; private byte[] tDesIV; public byte[] TDesKey { get { return this.tDesKey; } set { this.tDesKey = value; } } public byte[] TDesIV { get { return this.tDesIV; } set { this.tDesIV = value; } } public void CreateRandomCodon() { RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); byte[] newkey = new byte[KeySize]; rng.GetBytes(newkey); this.TDesKey = newkey; byte[] newiv = new byte[IVSize]; rng.GetBytes(newiv); this.tDesIV = newiv; } public static readonly int KeySize = 24; public static readonly int IVSize = 8; public string EncryptToBase64String(string OriginalString) { MemoryStream outputStream = new MemoryStream(); CryptoStream cs = new CryptoStream(outputStream, new TripleDESCryptoServiceProvider().CreateEncryptor(this.TDesKey, this.TDesIV), CryptoStreamMode.Write); byte[] originalBytes = System.Text.Encoding.UTF8.GetBytes(OriginalString); cs.Write(originalBytes, 0, originalBytes.Length); cs.FlushFinalBlock(); return Convert.ToBase64String(outputStream.ToArray()); } public string DecryptFromBase64String(string Base64String) { try { MemoryStream outputStream = new MemoryStream(); CryptoStream cs = new CryptoStream(outputStream, new TripleDESCryptoServiceProvider().CreateDecryptor(this.TDesKey, this.TDesIV), CryptoStreamMode.Write); byte[] inputBytes = Convert.FromBase64String(Base64String); cs.Write(inputBytes, 0, inputBytes.Length); cs.FlushFinalBlock(); return new System.Text.UTF8Encoding().GetString(outputStream.ToArray()); } catch (Exception ex) { throw new TDesDecryptException(ex.Message, ex); } } } }
程序代码:
using System; using System.Collections.Generic; using System.Text; namespace BlogLan.Web.Controls { public class TDesDecryptException : Exception { public TDesDecryptException(string Message, Exception InnerException) : base(Message, InnerException) { } } }
程序代码:
using System; using System.Collections.Generic; using System.Text; using System.Web.UI.Design; using System.Web.UI; using System.Drawing; using System.Drawing.Imaging; namespace BlogLan.Web.Controls.Designer { public class VerificationCodeDesigner : ControlDesigner { private VerificationCode vCode; public override bool AllowResize { get { return false; } } public override string GetDesignTimeHtml() { HtmlTextWriter writer = new HtmlTextWriter(new StringWriter()); this.vCode.GetDesignTimeCode(writer); string result = writer.InnerWriter.ToString(); writer.Close(); return result; //return base.GetDesignTimeHtml(); } public override void Initialize( component) { if (!(component is VerificationCode)) { throw new ArgumentException("Component must be a CerificationCode WebControl"); } this.vCode = (VerificationCode)component; base.Initialize(component); } } }
以上已经是完备的代码,并且添加了大量注释。
声明一下,以上代码都是自己写的。贴出着段代码的意义在于激发各位的思考解决问题的能力。
希望有所用。