随手记_C#验证码
前言
最近在网上偶然看见一个验证码,觉得很有意思,于是搜了下,是使用第三方实现的,先看效果:
总体来说效果还是可以的,官方提供的SDK也比较详细,可配置性很高。在这里在简单啰嗦几句使用方式:
使用步骤
①进入官网下载sdk接口→ http://www.geetest.com/install/ ,因为小弟是做C#的,所以此处选择C#,具体选择看各位大佬所用语言决定~
②第二步,获取代码,访问红框所示地址,下载demo。
③运行Demo(src文件夹里面的GeetestSDK项目)
④移植到自己项目中
⑴先将上述src文件拷贝到本地项目根目录下面
⑵然后打开本地项目并添加现有项目,将GeetestSDK添加进来
⑶在本地项目中添加引用
⑷View中新建容器存放验证码
@using (Html.BeginForm()) { <div> 用户名: </div> <div> @Html.TextBoxFor(model => model.Name) </div> <div> 密码: </div> <div> @Html.PasswordFor(model => model.Age) </div> <div> 验证码:<div id="captcha"></div> @*新增的存放验证码的容器*@ </div> <div> <input type="submit" value="登陆" /> </div> }
界面入下图:
⑸新建一个控制器(GetcaptchaController)和分部视图(Index)用于显示请求到的页面
控制器代码
public ActionResult Index() { Response.ContentType = "application/json"; Response.Write(getCaptcha()); Response.End(); return View(); } private String getCaptcha() { GeetestLib geetest = new GeetestLib(GeetestConfig.publicKey, GeetestConfig.privateKey); String userID = "ShowTime"; Byte gtServerStatus = geetest.preProcess(userID); Session[GeetestLib.gtServerStatusSessionKey] = gtServerStatus; Session["userID"] = userID; return geetest.getResponseStr(); }
其中,GeetestConfig是新建的一个类,里面代码如下:
public const String publicKey = "b46d1900d0a894591916ea94ea91bd2c"; public const String privateKey = "36fc3fe98530eea08dfc6ce76e3d24c4";
注:需要引入此命名空间 using GeetestSDK;
Index视图里面放一个空div就行,代码如下:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form id="form1"> <div> </div> </form> </body> </html>
⑹使用Ajax在登录页加载分部视图Index用于显示验证码
var handler = function (captchaObj) { //将验证码加到id为captcha的元素里 captchaObj.appendTo("#captcha"); }; //极验 $.ajax({ // 获取id,challenge,success(是否启用failback) url: "/Getcaptcha/Index", type: "get", dataType: "json", // 使用jsonp格式 success: function (data) { // 使用initGeetest接口 // 参数1:配置参数,与创建Geetest实例时接受的参数一致 // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件 initGeetest({ gt: data.gt, challenge: data.challenge, product: "float", // 产品形式 offline: !data.success }, handler); } });
注:需在头部引入Jquery1.9可直接引入下面两个js
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> <script src="http://static.geetest.com/static/tools/gt.js"></script>
⑺在登陆按钮中判断验证是否通过,登陆的Index代码如下:
[HttpPost] public ActionResult Index(Models.HelloModel loginModel) { GeetestLib geetest = new GeetestLib(GeetestConfig.publicKey, GeetestConfig.privateKey); Byte gt_server_status_code = (Byte)Session[GeetestLib.gtServerStatusSessionKey]; String userID = (String)Session["userID"]; int result = 0; String challenge = Request.Form.Get(GeetestLib.fnGeetestChallenge); String validate = Request.Form.Get(GeetestLib.fnGeetestValidate); String seccode = Request.Form.Get(GeetestLib.fnGeetestSeccode); if (gt_server_status_code == 1) result = geetest.enhencedValidateRequest(challenge, validate, seccode, userID); else result = geetest.failbackValidateRequest(challenge, validate, seccode); if (result == 1) Response.Write("success");//返回1则表明验证通过,可跳转页面或者做其他处理 else Response.Write("fail"); return View(); }
运行效果
另:官方Demo下载下来是使用的嵌入式的验证效果,要更改此效果,可参考客户端SDK参数来配置
链接→ http://www.geetest.com/install/sections/idx-client-sdk.html#id19
Demo下载
链接: 点我下载 密码:63pd
常规验证码
最终效果
HTML
<div style="MARGIN-TOP: 12px; margin-left: 0px; width: 130px; float: left;" id="checkInputLine" class="loginFormIpt showPlaceholder"> <input id="checkInput" class="loginFormCheckCodeInput" title='Please enter the contents of the right picture' tabindex="4" maxlength="5" require="True" title='验证码' placeholder="验证码" type="text" name="vcode" /> </div> <!-- 请输入验证码--> <img id="checkloing" src="/Home/VCode" class="loginFormCheckCodeImg" onclick="reloadcode('/Home/VCode')" title="Can not see clearly, change one." />
Ajax 请求如下:
//刷新验证码 function reloadcode(srcStr) { document.getElementById("checkloing").src = srcStr + "?rand=" + Math.random(); } var checkInfo = ""; //检查数据 function Check() { checkInfo = ""; //检查不能为空的数据 $("input[Require='True']").each(function (i) { var tmpName = $(this).attr("name"); var strVal = $(this).val(); strVal = strVal.replace(/\s/g, "") if (!strVal) checkInfo += $(this).attr("placeholder") + "不能为空。<br/>"; }); if (checkInfo) return false; return true; } $(function () { $("#btnLogin").click(function () { var ii = layer.load(); if (!Check()) { layer.close(ii); layer.msg('' + checkInfo, function () { }); return; } $("#loadingDiv").show(); $.ajax({ url: "/Home/Index", type: "post", data: "userName=" + $("#tbUserName").val() + "&pwd=" + $("#tbPWD").val() + "&code=" + $("#checkInput").val(), success: function (data) { debugger; if (data.Result == "0") { layer.close(ii); layer.msg('' + data.MSG); return; } else if (data.Result == "1") { layer.close(ii); window.location.href = "/Home/Index"; } }, error: function (data) { layer.close(ii); layer.msg('' + data.MSG); } }); }); });
其中:
layer.msg('' + data.MSG); 这种弹框方式使用了layer弹出层
Home控制器里面的VCde方法就是获取到最新的验证码,代码如下:
[AllowAnonymous]//跳过登陆验证 public ActionResult VCode() { VerificationCodeHelper vcode = new VerificationCodeHelper(); string codeStr = vcode.GetRandomCode(); if (!string.IsNullOrEmpty(codeStr)) { byte[] arrImg = vcode.GetVCode(codeStr); Session["code"] = codeStr; return File(arrImg, "image/gif"); } else { return RedirectToAction("/Login/VCode?rand=" + Guid.NewGuid().ToString().Substring(1, 10), "image/jpeg"); } }
其中 VerificationCodeHelper 就是封装好的 生成验证码的类,直接使用就行,代码如下:
public class VerificationCodeHelper { private static Color BackColor = Color.White; private static int Width = 62; private static int Height = 21; private Random _random; // private string _code; private int _brushNameIndex; public byte[] GetVCode(string codeStr) { _random = new Random(); using (Bitmap img = new Bitmap(Width, Height)) { // _code = GetRandomCode(); // System.Web.HttpContext.Current.Session["vcode"] = _code; using (Graphics g = Graphics.FromImage(img)) { g.Clear(Color.White);//绘画背景颜色 Paint_Text(g, codeStr);// 绘画文字 // g.DrawString(strCode, new Font("微软雅黑", 15), Brushes.Blue, new PointF(5, 2));// 绘画文字 Paint_TextStain(img);// 绘画噪音点 g.DrawRectangle(Pens.DarkGray, 0, 0, Width - 1, Height - 1);//绘画边框 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { //将图片 保存到内存流中 img.Save(ms, System.Drawing.Imaging.ImageFormat.Gif); //将内存流 里的 数据 转成 byte 数组 返回 return ms.ToArray(); } } } } /// <summary> /// 绘画文字 /// </summary> /// <param name="g"></param> private void Paint_Text(Graphics g, string code) { g.DrawString(code, GetFont(), GetBrush(), 3, 1); } /// <summary> /// 绘画文字噪音点 /// </summary> /// <param name="g"></param> private void Paint_TextStain(Bitmap b) { string[] BrushName = new string[] { "OliveDrab", "ForestGreen", "DarkCyan", "LightSlateGray", "RoyalBlue", "SlateBlue", "DarkViolet", "MediumVioletRed", "IndianRed", "Firebrick", "Chocolate", "Peru", " enrod" }; for (int n = 0; n < 30; n++) { int x = _random.Next(Width); int y = _random.Next(Height); b.SetPixel(x, y, Color.FromName(BrushName[_brushNameIndex])); } } /// <summary> /// 随机取一个字体 /// </summary> /// <returns></returns> private Font GetFont() { string[] FontItems = new string[]{ "Arial", "Helvetica", "Geneva", "sans-serif", "Verdana" }; int fontIndex = _random.Next(0, FontItems.Length); FontStyle fontStyle = GetFontStyle(_random.Next(0, 2)); return new Font(FontItems[fontIndex], 12, fontStyle); } /**/ /**/ /**/ /// <summary> /// 随机取一个笔刷 /// </summary> /// <returns></returns> private Brush GetBrush() { Brush[] BrushItems = new Brush[]{ Brushes.OliveDrab, Brushes.ForestGreen, Brushes.DarkCyan, Brushes.LightSlateGray, Brushes.RoyalBlue, Brushes.SlateBlue, Brushes.DarkViolet, Brushes.MediumVioletRed, Brushes.IndianRed, Brushes.Firebrick, Brushes.Chocolate, Brushes.Peru, Brushes.Goldenrod }; int brushIndex = _random.Next(0, BrushItems.Length); _brushNameIndex = brushIndex; return BrushItems[brushIndex]; } /// <summary> /// 绘画背景颜色 /// </summary> /// <param name="g"></param> private void Paint_Background(Graphics g) { g.Clear(BackColor); } /**/ /**/ /**/ /// <summary> /// 取一个字体的样式 /// </summary> /// <param name="index"></param> /// <returns></returns> private FontStyle GetFontStyle(int index) { switch (index) { case 0: return FontStyle.Bold; case 1: return FontStyle.Italic; default: return FontStyle.Regular; } } /// <summary> /// 取得一个 4 位的随机码 /// </summary> /// <returns></returns> public string GetRandomCode() { return Guid.NewGuid().ToString().Substring(0, 5); } }
注意,初次加载页面的时候,将拿到的code存入Session中,点击登录的时候,将用户输入的验证码传入后台,进行比对验证是否和Session中的验证码相同,如果相同,则允许登录,否则,验证码错误
参考Action如下:
[HttpPost] public ActionResult Index(string userName, string pwd) { try { string vccode = Request.Form["code"]; if (string.IsNullOrEmpty(vccode)) return Json(new { Result = "0", MSG = "请填写验证码" }); else { if (Session["code"] == null) return Json(new { Result = "0", MSG = "验证码已过期,请点击刷新验证码" }); string str = Session["code"].ToString(); str = str.ToLower(); vccode = vccode.ToLower(); if (str != vccode) return Json(new { Result = "0", MSG = "验证码填写错误!" }); else { Session["code"] = null; } if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(pwd)) { return Json(new { Result = "0", MSG = "用户或密码没有填写" }); } //查询此用户 #region 查询此用户 List<Models.MySqlUser> adminml = new List<Models.MySqlUser>(); Models.MySqlUser admin = new Models.MySqlUser(); adminml = IBCodeBll.GetModelList(userName.Trim()); if (adminml.Count > 0) { if (!adminml[0].password.ToLower().Equals(Maticsoft.Common.DEncrypt.DESEncrypt.Encrypt2(pwd.Trim()).ToLower())) { return Json(new { Result = "0", MSG = "密码错误!" }); } } else { return Json(new { Result = "0", MSG = "用户不在在!" }); } #endregion Session["UserName"] = userName.Trim().ToString(); return Json(new { Result = "1", MSG = "登录成功!" }); } } catch (Exception ex) { return Json(new { Result = "0", MSG = ex.Message }); } }
End!
- 感谢你的阅读。如果你觉得这篇文章对你有帮助或者有启发,就请推荐一下吧~你的精神支持是博主强大的写作动力。欢迎转载!
- 博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高(其实是个菜B),不足和错误之处在所难免,希望大家能够批评指出。
- 欢迎加入.NET 从入门到精通技术讨论群→523490820 期待你的加入
- 不舍得打乱,就永远学不会复原。被人嘲笑的梦想,才更有实现的价值。
- 我的博客:http://www.cnblogs.com/zhangxiaoyong/