在做Asp.Net Mvc开发过程中,或多或少会遇到需要验证码的地方,像用户登录、注册的时候会需要验证码,防止一些黑客进行暴力破解登陆,或恶意注册用户从而导致服务器崩溃,所以这里我记下创建验证码的方法。
下面这三点是生成验证码的步骤:如下
1、生成随机码。
2、根据随机码绘画图片
1)根据随机码的数量,计算图片的宽度。
2)设定图片的高度。
3)根据宽度与高度创建图片对象。
4)通过图片对象创建绘画对象,并清除背景色。
5)设置干扰线的数量,并随机绘画干扰线,干扰线的颜色用浅颜色。
6)绘画随机码。
7)返回图片对象。
3、将生成的图片对象转换成字节数组并返回到浏览器上,显示验证码。
转换成代码如下所示。
using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Text; using System.Web.Mvc; namespace Paduc.WA.PaducWebApplication.Controllers { public class VerificationCodeController : Controller { // // GET: /VerificationCode/ /// <summary> /// 获取图片 /// </summary> /// <returns></returns> public ActionResult GetCode() { ///获取随机码 var code = getRandomStr(4); ///生成图片对象 var bitmap = getImage(code, "ch"); ///图片对象转为字节数组 byte[] data = bitmapToByte(bitmap); ///输出文件 return File(data, "image/gif"); } /// <summary> /// 获取随机码 /// </summary> /// <param name="count">随机码个数</param> /// <returns>随机码</returns> private string getRandomStr(int count) { if (count == 0) throw new ArgumentException("错误的字符长度!", "strCount"); StringBuilder sb = new StringBuilder(); var strs = "0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w s y z " + "A B C D E F G H I J K L M N O P Q R S T U V W S Y Z"; var strArray = strs.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); Random random = new Random(); for (int i = 0; i < count; i++) { sb.Append(strArray[random.Next(strArray.Length)]); } return sb.ToString(); } /// <summary> /// 根据随机码生成bitmap对象 /// </summary> /// <param name="code">随机码</param> /// <param name="type">en,ch</param> /// <returns>bitmap对象</returns> private Bitmap getImage(string code, string type = "en") { if (string.IsNullOrWhiteSpace(code)) throw new ArgumentException("随机码为空!", "type"); int step = 0; if (type == "ch") { step = 5; } ///英文字符个数 int charLength = code.Length; ///bitmap的宽度(像素) int iWidth = charLength * (13 + step); ///bitmap的高度(像素) int iHeight = 22; ///创建图片 Bitmap image = new Bitmap(iWidth, iHeight); ///绘画图片对象 Graphics g = Graphics.FromImage(image); ///清除背景并填充白色 g.Clear(Color.White); ///画干扰点 Random random = new Random(); for (int i = 0; i < 50; i++) { int x1 = random.Next(iWidth); int x2 = random.Next(iWidth); int y1 = random.Next(iHeight); int y2 = random.Next(iHeight); g.DrawLine(new Pen(Color.LightGray, 1), x1, y1, x2, y2); } ///字体颜色 Color[] colors = new Color[] { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange }; ///字体设置 string[] fontFamilies = new string[] { "黑体", "Bahnschrift SemiLight", "Comic Sans MS", "MV Boli", "Segoe Print" }; for (int i = 0; i < charLength; i++) { int colorIndex = random.Next(colors.Length); int fontIndex = random.Next(fontFamilies.Length); ///随机字体 Font font = new Font(fontFamilies[fontIndex], 10, FontStyle.Bold); ///用来填充多边形的内部对象(填充字体) Brush brush = new SolidBrush(colors[colorIndex]); ///开始绘画字符 g.DrawString(code.Substring(i, 1), font, brush, i * (12 + step), 4); } ///绘画矩形边框 //g.DrawRectangle(new Pen(Color.Red, 1), 0, 0, image.Width - 1, image.Height - 1); return image; } /// <summary> /// bitmap对象转换为字节数组 /// </summary> /// <param name="bitmap"></param> /// <returns></returns> private byte[] bitmapToByte(Bitmap bitmap) { using (MemoryStream ms = new MemoryStream()) { ///bitmap保存到流对象 bitmap.Save(ms, ImageFormat.Jpeg); ///流对象设置开始位置 ms.Seek(0, SeekOrigin.Begin); byte[] data = new byte[ms.Length]; ///从流对象中读取字节块,将数据写入到字节数组 ms.Read(data, 0, data.Length); return data; } } } }