有如下特性:
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.Collections.Generic;
using System.ComponentModel;
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.IO;
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);
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = 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.Collections.Generic;
using System.Text;
namespace BlogLan.Web.Controls
{
/// <summary>
/// 验证码图片格式。
/// </summary>
public enum VerificationCodeImageFormat
{
Gif,
Jpeg
}
}
using System.Collections.Generic;
using System.Text;
namespace BlogLan.Web.Controls
{
/// <summary>
/// 表示噪音渲染的位置模式。
/// </summary>
public enum VerificationCodeNoiseRenderMode
{
/// <summary>
/// 噪音在背景上渲染。
/// </summary>
Back,
/// <summary>
/// 噪音在文字前方渲染。
/// </summary>
Front
}
}
using System.Collections.Generic;
using System.Text;
namespace BlogLan.Web.Controls
{
/// <summary>
/// 噪音类型。
/// </summary>
public enum VerificationCodeNoiseType
{
/// <summary>
/// 点
/// </summary>
Spot,
/// <summary>
/// 线
/// </summary>
Line
}
}
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Web.UI;
using System.IO;
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.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace 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.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.IO;
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(System.ComponentModel.IComponent component)
{
if (!(component is VerificationCode))
{
throw new ArgumentException("Component must be a CerificationCode WebControl");
}
this.vCode = (VerificationCode)component;
base.Initialize(component);
}
}