前言
最近在网上偶然看见一个验证码,觉得很有意思,于是搜了下,是使用第三方实现的,先看效果:
总体来说效果还是可以的,官方提供的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 = ;
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 == ) result = geetest.enhencedValidateRequest(challenge, validate, seccode, userID);
else result = geetest.failbackValidateRequest(challenge, validate, seccode);
if (result == ) 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(, ), "image/jpeg");
}
}
其中 VerificationCodeHelper 就是封装好的 生成验证码的类,直接使用就行,代码如下:
public class VerificationCodeHelper
{
private static Color BackColor = Color.White;
private static int Width = ;
private static int Height = ;
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, , , Width - , Height - );//绘画边框
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(), , );
} /// <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 = ; n < ; 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(, FontItems.Length);
FontStyle fontStyle = GetFontStyle(_random.Next(, ));
return new Font(FontItems[fontIndex], , 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(, 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 :
return FontStyle.Bold;
case :
return FontStyle.Italic;
default:
return FontStyle.Regular;
}
} /// <summary>
/// 取得一个 4 位的随机码
/// </summary>
/// <returns></returns>
public string GetRandomCode()
{
return Guid.NewGuid().ToString().Substring(, );
}
}
注意,初次加载页面的时候,将拿到的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 = "", MSG = "请填写验证码" });
else
{
if (Session["code"] == null)
return Json(new { Result = "", MSG = "验证码已过期,请点击刷新验证码" });
string str = Session["code"].ToString();
str = str.ToLower();
vccode = vccode.ToLower();
if (str != vccode)
return Json(new { Result = "", MSG = "验证码填写错误!" });
else
{
Session["code"] = null;
}
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(pwd))
{
return Json(new { Result = "", MSG = "用户或密码没有填写" });
}
//查询此用户
#region 查询此用户
List<Models.MySqlUser> adminml = new List<Models.MySqlUser>();
Models.MySqlUser admin = new Models.MySqlUser();
adminml = IBCodeBll.GetModelList(userName.Trim()); if (adminml.Count > )
{
if (!adminml[].password.ToLower().Equals(Maticsoft.Common.DEncrypt.DESEncrypt.Encrypt2(pwd.Trim()).ToLower()))
{
return Json(new { Result = "", MSG = "密码错误!" });
}
}
else
{
return Json(new { Result = "", MSG = "用户不在在!" });
}
#endregion
Session["UserName"] = userName.Trim().ToString();
return Json(new { Result = "", MSG = "登录成功!" });
}
}
catch (Exception ex)
{ return Json(new { Result = "", MSG = ex.Message });
}
}
End!