MVC中验证码的实现(经常用,记录备用)
一、目录
1、多层架构+MVC+EF+AUTOFAC+AUTOMAPPER;
2、MVC中验证码的实现(经常用,记录备用)
二 正文
Ok,我们的验证码开始,这篇文章不写怎么生成验证码,意在将MVC下几个验证码方法贴出来,大家以后需要的时候直接调用就行了。
我们的框架中有上图这么一个类,里面有生成验证码的两个方法,位于框架中的基础设施层当中:
1 namespace YTJWGL_Common
2 {
3 public class ValidatorCodeTools
4 {
5 #region 生成校验码图片
6 public ValidatorCodeTools()
7 {
8 }
9 /// <summary>
10 /// 验证码的最大长度
11 /// </summary>
12 public int MaxLength
13 {
14 get { return 10; }
15 }
16 /// <summary>
17 /// 验证码的最小长度
18 /// </summary>
19 public int MinLength
20 {
21 get { return 1; }
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 /// <summary>
67 /// 创建验证码的图片
68 /// </summary>
69 /// <param name="validateCode">验证码内容</param>
70 /// <returns></returns>
71 public byte[] CreateValidateGraphic(string validateCode)
72 {
73 Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22);
74 Graphics g = Graphics.FromImage(image);
75 try
76 {
77 //生成随机生成器
78 Random random = new Random();
79 //清空图片背景色
80 g.Clear(Color.White);
81 //画图片的干扰线
82 for (int i = 0; i < 25; i++)
83 {
84 int x1 = random.Next(image.Width);
85 int x2 = random.Next(image.Width);
86 int y1 = random.Next(image.Height);
87 int y2 = random.Next(image.Height);
88 g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
89 }
90 Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));
91 LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
92 Color.Blue, Color.DarkRed, 1.2f, true);
93 g.DrawString(validateCode, font, brush, 3, 2);
94 //画图片的前景干扰点
95 for (int i = 0; i < 100; i++)
96 {
97 int x = random.Next(image.Width);
98 int y = random.Next(image.Height);
99 image.SetPixel(x, y, Color.FromArgb(random.Next()));
100 }
101 //画图片的边框线
102 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
103 //保存图片数据
104 MemoryStream stream = new MemoryStream();
105 image.Save(stream, ImageFormat.Jpeg);
106 //输出图片流
107 return stream.ToArray();
108 }
109 finally
110 {
111 g.Dispose();
112 image.Dispose();
113 }
114 }
115 /// <summary>
116 /// 得到验证码图片的长度
117 /// </summary>
118 /// <param name="validateNumLength">验证码的长度</param>
119 /// <returns></returns>
120 public static int GetImageWidth(int validateNumLength)
121 {
122 return (int)(validateNumLength * 12.0);
123 }
124 /// <summary>
125 /// 得到验证码的高度
126 /// </summary>
127 /// <returns></returns>
128 public static double GetImageHeight()
129 {
130 return 22.5;
131 }
132 #endregion
133 }
134 }
CreateValidateCode方法生成验证码内容,对应图片中的形如“54361”这样的数字。而CreateValidateGraphic该方法接收一个参数,把参数中的验证码转换为图片显示。
接下来,在BLL层有两个方法:
1 namespace YTJWGL_Bll
2 {
3 public class AdminService : BaseService<YTJWGL_Admin>, IAdminService
4 {
5
6
7 /// <summary>
8 /// 生成验证码数字
9 /// </summary>
10 /// <param name="id">验证码位数,默认为5</param>
11 /// <returns></returns>
12 public string NewValidateCode(int id = 5)
13 {
14 ValidatorCodeTools obj = new ValidatorCodeTools();
15 return obj.CreateValidateCode(5);
16 }
17 /// <summary>
18 /// 验证码图片
19 /// </summary>
20 /// <param name="code"></param>
21 /// <returns></returns>
22 public byte[] NewValidateCodeGraphic(string code)
23 {
24 ValidatorCodeTools obj = new ValidatorCodeTools();
25 return obj.CreateValidateGraphic(code);
26 }
27 }
28 }
没什么好稀奇,就是调用基础设施层的两个方法。
到这,我们的菜的“调料”已经备齐,下一步就是“炒菜”了。
在你自己认为合适的控制器中新建一个Action:
1 namespace YTJWGL_WebUI.Areas.Admin.Controllers
2 {
3
4 public class FrameController : Controller
5 {
6 //
7 // GET: /Admin/Frame/
8 #region Fields
9
10 private readonly IAdminService _adminService;
11 private readonly IAdminAuthorityService _adminAuthorityService;
12 private readonly IAdminRoleService _adminRoleService;
13 private readonly ILogService _logService;
14
15
16 #endregion
17
18 #region Constructors
19
20
21
22 public FrameController(IAdminService adminService, IAdminAuthorityService adminAuthorityService, IAdminRoleService adminRoleService, ILogService logService)
23 {
24 this._adminService = adminService;
25 this._adminAuthorityService = adminAuthorityService;
26 this._adminRoleService = adminRoleService;
27 this._logService = logService;
28 }
29 #endregion
30
31 #region Admin
32
33 public ActionResult GetValidatorGraphics()
34 {
35 string code = _adminService.NewValidateCode();
36 Session["ValidatorCode"] = code;
37 byte[] graphic = _adminService.NewValidateCodeGraphic(code);
38 return File(graphic, @"image/jpeg");
39 }
40 #endregion
41 }
42 }
在Action中调用我们刚才在BLL层定义的两个方法,返回这张验证码图片。因为http是无连接的,这个action仅仅响应用户一次访问请求,当用户点击登录后会将填写的验证码发送到服务器,而这已经是第二次访问请求了,所以需要用Session用来保存刚才发往客户端的验证码。
那么,怎么在界面上请求这张验证码图片呢?
1 <div class="editor-filed">
2 <img id="valiCode" src="@Url.Action("GetValidatorGraphics", "Frame")" title="看不清?点击更换图片。" />
3 <input data-val="true" data-val-required="请按图填定验证码中的字母。" type="text" name="ValidatorCode"
4 style="width: 60px;" />
5 @Html.ValidationMessage("ValidatorCode")
6 </div>
相当简单,只需要使用<img>标签的src属性访问我们刚才的action。
生成的效果在这:
对于有特殊样式需求的验证码,基础层中的两个方法需要重写,但是大部分情形下,这样的效果已经能满足需求了。
到了最后一步喽:点击图片,刷新我们验证码图片中的数字,这个必须的,也很Easy。
1 <script type="text/javascript">
2 //当点击图片时,刷新验证码
3 $(function () {
4 $("#valiCode").bind("click", function () {
5 this.src = "@Url.Action("GetValidatorGraphics", "Frame")?time=" + (new Date()).getTime();
6 });
7 });
8 </script>
给img标签添加click事件,点击过后重新访问生成验证码的action,由于验证中数字是随机生成的,新返回的验证码图片就不一样了。避免浏览器缓存影响,src链接附件了一个随机时间。
有需要的同学们copy CreateValidateCode,CreateValidateGraphic ……
下一篇,我们搭建Ligerui 的官网首页:http://www.ligerui.com/