最近因为有个项目除了登录还有其他很多地方需要用到验证码的功能,所以想到了采用HtmlHelper和ActionFilter封装一个验证码的功能,以便能够重复调用。封装好以后调用很方便,只需在View中调用Html扩展好的方法,相应的Action加上验证功能的Filter就行了。
首先写一个能够随机生成数字的图片的类,园子里有一大把这样的文章,直接拿过来就用了,自己懒得写了。
1 public class CaptchaRender 2 { 3 public CaptchaRender() 4 { 5 } 6 7 /// <summary> 8 /// 验证码的最大长度 9 /// </summary> 10 public int MaxLength 11 { 12 get { return 10; } 13 } 14 15 /// <summary> 16 /// 验证码的最小长度 17 /// </summary> 18 public int MinLength 19 { 20 get { return 1; } 21 } 22 23 /// <summary> 24 /// 生成验证码 25 /// </summary> 26 /// <param name="length">指定验证码的长度</param> 27 /// <returns></returns> 28 public string CreateValidateCode(int length) 29 { 30 int[] randMembers = new int[length]; 31 int[] validateNums = new int[length]; 32 string validateNumberStr = ""; 33 //生成起始序列值 34 int seekSeek = unchecked((int) DateTime.Now.Ticks); 35 Random seekRand = new Random(seekSeek); 36 int beginSeek = (int) seekRand.Next(0, Int32.MaxValue - length*10000); 37 int[] seeks = new int[length]; 38 for (int i = 0; i < length; i++) 39 { 40 beginSeek += 10000; 41 seeks[i] = beginSeek; 42 } 43 //生成随机数字 44 for (int i = 0; i < length; i++) 45 { 46 Random rand = new Random(seeks[i]); 47 int pownum = 1*(int) Math.Pow(10, length); 48 randMembers[i] = rand.Next(pownum, Int32.MaxValue); 49 } 50 //抽取随机数字 51 for (int i = 0; i < length; i++) 52 { 53 string numStr = randMembers[i].ToString(); 54 int numLength = numStr.Length; 55 Random rand = new Random(); 56 int numPosition = rand.Next(0, numLength - 1); 57 validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1)); 58 } 59 //生成验证码 60 for (int i = 0; i < length; i++) 61 { 62 validateNumberStr += validateNums[i].ToString(); 63 } 64 return validateNumberStr; 65 } 66 67 /// <summary> 68 /// 创建验证码的图片 69 /// </summary> 70 /// <param name="containsPage">要输出到的page对象</param> 71 /// <param name="validateNum">验证码</param> 72 public byte[] CreateValidateGraphic(string validateCode) 73 { 74 Bitmap image = new Bitmap((int) Math.Ceiling(validateCode.Length*12.0), 22); 75 Graphics g = Graphics.FromImage(image); 76 try 77 { 78 //生成随机生成器 79 Random random = new Random(); 80 //清空图片背景色 81 g.Clear(Color.White); 82 //画图片的干扰线 83 for (int i = 0; i < 25; i++) 84 { 85 int x1 = random.Next(image.Width); 86 int x2 = random.Next(image.Width); 87 int y1 = random.Next(image.Height); 88 int y2 = random.Next(image.Height); 89 g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); 90 } 91 Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); 92 LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), 93 Color.Blue, Color.DarkRed, 1.2f, true); 94 g.DrawString(validateCode, font, brush, 3, 2); 95 //画图片的前景干扰点 96 for (int i = 0; i < 100; i++) 97 { 98 int x = random.Next(image.Width); 99 int y = random.Next(image.Height); 100 image.SetPixel(x, y, Color.FromArgb(random.Next())); 101 } 102 //画图片的边框线 103 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); 104 //保存图片数据 105 MemoryStream stream = new MemoryStream(); 106 image.Save(stream, ImageFormat.Jpeg); 107 //输出图片流 108 return stream.ToArray(); 109 } 110 finally 111 { 112 g.Dispose(); 113 image.Dispose(); 114 } 115 } 116 117 /// <summary> 118 /// 得到验证码图片的长度 119 /// </summary> 120 /// <param name="validateNumLength">验证码的长度</param> 121 /// <returns></returns> 122 public static int GetImageWidth(int validateNumLength) 123 { 124 return (int) (validateNumLength*12.0); 125 } 126 127 /// <summary> 128 /// 得到验证码的高度 129 /// </summary> 130 /// <returns></returns> 131 public static double GetImageHeight() 132 { 133 return 22.5; 134 } 135 }