ASP.net 验证码(C#) MVC
网站添加验证码,主要为防止机器人程序批量注册,或对特定的注册用户用特定程序暴力破解方式,以进行不断的登录、灌水等危害网站的操作。验证码被广泛应用在注册、登录、留言等提交信息到服务器端处理的页面中。
在ASP.NET网站中应用验证码是很容易的,网上有很多的解决方案。最近在做一个OA项目,因系统采用的ASP.NET MVC框架,同样在登录页中需用到验证码,故需将原来在ASP.NET网站中使用的验证码移植到ASP.NET MVC中。 原ASP.NET网站用来生成验证码的类文件ValidateCode.cs: using System;using System.Drawing;using System.Drawing.Imaging;using System.Web.UI;using System.Drawing.Drawing2D;using System.IO;namespace SeniOA.MVC{ /// <summary>/// 生成验证码的类/// </summary>public class ValidateCode { public ValidateCode() { }/// <summary>/// 验证码的最大长度/// </summary>public int MaxLength { get { return 10; } }/// <summary>/// 验证码的最小长度/// </summary>public int MinLength { get { return 1; } }/// <summary>/// 生成验证码/// </summary>/// <param name="length">指定验证码的长度</param>/// <returns></returns>public string CreateValidateCode(int length) { int[] randMembers = new int[length];int[] validateNums = new int[length];string validateNumberStr = "";//生成起始序列值int seekSeek = unchecked((int)DateTime.Now.Ticks); Random seekRand = new Random(seekSeek);int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - length * 10000);int[] seeks = new int[length];for (int i = 0; i < length; i++) { beginSeek += 10000; seeks[i] = beginSeek; }//生成随机数字for (int i = 0; i < length; i++) { Random rand = new Random(seeks[i]);int pownum = 1 * (int)Math.Pow(10, length); randMembers[i] = rand.Next(pownum, Int32.MaxValue); }//抽取随机数字for (int i = 0; i < length; i++) { string numStr = randMembers[i].ToString();int numLength = numStr.Length; Random rand = new Random();int numPosition = rand.Next(0, numLength - 1); validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1)); }//生成验证码for (int i = 0; i < length; i++) { validateNumberStr += validateNums[i].ToString(); }return validateNumberStr; }/// <summary>/// 创建验证码的图片/// </summary>/// <param name="containsPage">要输出到的page对象</param>/// <param name="validateNum">验证码</param>public void CreateValidateGraphic(string validateCode) { Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22); Graphics g = Graphics.FromImage(image);try { //生成随机生成器 Random random = new Random();//清空图片背景色 g.Clear(Color.White);//画图片的干扰线for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width);int x2 = random.Next(image.Width);int y1 = random.Next(image.Height);int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, 3, 2);//画图片的前景干扰点for (int i = 0; i < 100; i++) { int x = random.Next(image.Width);int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); }//画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);//保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg);//输出图片流 containsPage.Response.Clear(); containsPage.Response.ContentType = "image/jpeg"; containsPage.Response.BinaryWrite(stream.ToArray()); }finally { g.Dispose(); image.Dispose(); } }/// <summary>/// 得到验证码图片的长度/// </summary>/// <param name="validateNumLength">验证码的长度</param>/// <returns></returns>public static int GetImageWidth(int validateNumLength) { return (int)(validateNumLength * 12.0); }/// <summary>/// 得到验证码的高度/// </summary>/// <returns></returns>public static double GetImageHeight() { return 22.5; } }}为适合ASP.NET MVC框架,修改其输出图片流的方法CreateValidateGraphic为:
/// <summary>/// 创建验证码的图片/// </summary>/// <param name="containsPage">要输出到的page对象</param>/// <param name="validateNum">验证码</param>public byte[] CreateValidateGraphic(string validateCode){ Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22); Graphics g = Graphics.FromImage(image);try { //生成随机生成器 Random random = new Random();//清空图片背景色 g.Clear(Color.White);//画图片的干扰线for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width);int x2 = random.Next(image.Width);int y1 = random.Next(image.Height);int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, 3, 2);//画图片的前景干扰点for (int i = 0; i < 100; i++) { int x = random.Next(image.Width);int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); }//画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);//保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg);//输出图片流return stream.ToArray(); }finally { g.Dispose(); image.Dispose(); }}在Controller.cs中,添加Action,用来设置将生成的验证码存入Session,并输出验证码图片:
public ActionResult GetValidateCode(){ ValidateCode vCode = new ValidateCode();string code = vCode.CreateValidateCode(5); Session["ValidateCode"] = code;byte[] bytes = vCode.CreateValidateGraphic(code);return File(bytes, @"image/jpeg");}调用方式为:在需要使用验证码的页面中,加入<img>标签:
<img id="valiCode" style="cursor: pointer;" src="../Account/GetValidateCode" alt="验证码" /> 效果如下图: 到于Account/Login这个Action中的处理,只需加入对Session中验证码的判断: [AcceptVerbs(HttpVerbs.Post)]public ActionResult Login(string userName, string password, bool rememberMe, string returnUrl,string code){ if (Session["ValidateCode"].ToString() != code) { ModelState.AddModelError("code", "validate code is error");return View(); }//此处验证用户名、密码if (!ValidateLogOn(userName, password)) { return View(); }//验证成功 FormsAuthentication.SetAuthCookie(userName, rememberMe);if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); }else { return RedirectToAction("Index", "Home"); }}为实现登录页中,点击图片切换验证码,可以登录页中加入此JS代码实现刷新验证码:
<script type="text/javascript" src="http://www.cnblogs.com/Scripts/jquery-1.3.2-vsdoc.js"></script><script type="text/javascript"> $(function() { $("#valiCode").bind("click", function() { this.src = "../Account/GetValidateCode?time=" + (new Date()).getTime(); });//alert("good"); });</script>至此,ASP.NET MVC中已成功实现验证码功能。