WebSite---前台系统图片验证码心得
背景: 因为移动端APP和Msite手机注册发送短信验证码没有添加图片验证码功能。公司的短信接口被恶意刷取。所以我们就觉得在移动端添加一个图片验证码功能。分享一下大体实现方式思路。PS demo是自己写的。跟公司代码还是有很大差距的。
一. 图片验证码第一版
1. 建立图片验证码 ValidationCodeHelper
1.1 填写方法生成对应的.验证码: 默认是4位数字
private static char[] _constant = {
'','','','','','','','','','',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','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','X','Y','Z'
}; public static string CreateValidateCode(int length = , bool isNum = true)
{
var sb = new StringBuilder();
var constant = isNum ? _constant.Take().ToArray() : _constant;
var constant_count = constant.Count();
Random rd = new Random();
for (var index = ; index < length; index++)
{
sb.Append(constant[rd.Next(constant_count)]);
}
return sb.ToString();
}
1.2 通过验证码生成图片流, 此代码是从其他博友那里Copy过来的。自己对图片方面不擅长
public static byte[] GetImage(string code)
{
Bitmap image = new Bitmap((int)Math.Ceiling(code.Length * 16.0), );
Graphics g = Graphics.FromImage(image);
try
{
Random random = new Random();
g.Clear(Color.Gray);
for (int i = ; i < ; 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, x2, y1, y2);
}
Font font = new Font("Arial", , (FontStyle.Bold | FontStyle.Italic));
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(, , image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
g.DrawString(code, font, brush, , );
for (int i = ; i < ; 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), , , image.Width - , image.Height - );
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Jpeg);
return stream.ToArray();
}
catch (Exception ex)
{
return null;
}
finally
{
g.Dispose();
image.Dispose();
}
}
2. 封装一个简单的CookieHelper类型主要是对Cookie进行加密。只是简单封装, 没有对CookieHelper添加泛型,未支持Object处理。公司里面的CookieHelper库更强大。可是不能分享代码出来。所以自己简单的写了一个。
public class CookieHelper
{ #region 字符串加密解密 private static string _MD5 = "8ff0c65d-a2ed-4e1e-af85-690c08b8d039"; private static string Decrypt(string cipherString)
{
byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(cipherString);
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(_MD5));
hashmd5.Clear(); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(
toEncryptArray, , toEncryptArray.Length);
tdes.Clear();
return UTF8Encoding.UTF8.GetString(resultArray);
} private static string Encrypt(string toEncrypt)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(_MD5));
hashmd5.Clear(); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray =
cTransform.TransformFinalBlock(toEncryptArray, ,
toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, , resultArray.Length);
} #endregion #region Cookie public static void SaveCookie(string name, string value, int expiredSecond = )
{
var encryptStr = Encrypt(value);
var collection = HttpContext.Current.Response.Cookies;
collection.Add(new HttpCookie(name)
{
Value = encryptStr,
Expires = expiredSecond > ? System.DateTime.Now.AddSeconds(expiredSecond) : System.DateTime.MaxValue
});
} public static string GetCookie(string name)
{
var cookie = HttpContext.Current.Request.Cookies.Get(name);
if (cookie == null)
{
return null;
}
else
{
return Decrypt(cookie.Value);
}
} #endregion
}
3. Controller新增图片服务。设置图片的Cookie有效期是一分钟
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
} public FileContentResult ImageValidator()
{
var code = ValidationCodeHelper.CreateValidateCode();
CookieHelper.SaveCookie("PicCode", code, );
var picByte = ValidationCodeHelper.GetImage(code);
return File(picByte, "image/jpeg ");
} /// <summary>
/// 检查图片验证码是否正确
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public ActionResult CheckPicCode(string code)
{
var cookieCode = CookieHelper.GetCookie("PicCode");
if (string.IsNullOrWhiteSpace(cookieCode))
{
return Json("验证码过期",JsonRequestBehavior.AllowGet);
}
if (code.Trim().ToUpper() == cookieCode.ToUpper())
{
return Json("验证码正确",JsonRequestBehavior.AllowGet);
}
else
{
return Json("验证码错误",JsonRequestBehavior.AllowGet);
}
}
}
4.前台页面. 通过修改img的src链接,来实现点击刷新图片.
<head>
<title></title>
<script src="https://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<input type="text" id="inpCode" />
<img id="picCode" src="/Home/ImageValidator" />
<button id="btnCheck" >校验</button>
</body>
</html>
<script> $(function () { $("#picCode").on('click', function () {
$(this).attr('src', "/Home/ImageValidator?v=" + new Date().getTime());
}) $("#btnCheck").on('click', function () {
$.ajax({
type: 'get',
url: "/Home/CheckPicCode",
data: {
code:$("#inpCode").val()
},
success: function (data) {
alert(data);
}
})
}) }) </script>
5. 第一版基本代码实现了,点击图片刷新验证码,图片验证码有效期是一分钟.
一分钟内
一分钟后,验证码过期了
6.大家看上面两张图以为验证码OK了。的确。正常网站使用是OK的。因为我们设置了验证码的有效时间是一分钟。那我们看看Fiddler里面的效果。
当我面在Fiddler里面模拟的时候Cookie的过期时间是没有的。也就是如果客户端用户抓取了PicCode的Cookie后。自己构建请求的话。Cookie是不会失效的。
二. 图片验证码改版。
从上面看来 直接设置Cookie的过期时间是不行的。那我们只能在Cookie存储Value上修改了。来看看我们代码实现方式。我们将过期时间的ticks和验证码字符串同时加密存储在了Cookie中。
/// <summary>
/// 构建图片Cookie字符串,code和过期见时间用逗号隔开
/// </summary>
public static string BuildValidateCodeStorage(string code, int expiredSeconds = )
{
return string.Format("{0},{1}", code, System.DateTime.Now.AddSeconds(expiredSeconds).Ticks);
} /// <summary>
/// 解析图片验证码Cookie
/// </summary>
public static string AnysisValidateCode(string codeStorage)
{
if (string.IsNullOrWhiteSpace(codeStorage))
{
return null;
}
else
{
var vals = codeStorage.Split(',');
if (vals.Count() != )
{
return null;
}
else
{
long ticks = ;
long.TryParse(vals[], out ticks);
if (ticks > System.DateTime.Now.Ticks)
{
return vals[];
}
else
{
return null;
}
}
}
}
三.总结
这个是我们暂时想到的图片验证码实现方案。不知道其他博友公司是如何实现的。希望大家也可以分享一下。
http://files.cnblogs.com/files/FourLeafCloverZc/ImageValidation.zip
WebSite---前台系统图片验证码心得的更多相关文章
- Django实战(一)-----用户登录与注册系统5(图片验证码)
为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是一种区分用户是计算机还是人的公共全自动程序. 可以防止恶意破解密码.刷票.论坛 ...
- 项目一:第八天 1、前台系统导入 实现客户注册 发验证码,邮件 springdata-redis存储数据 3、实现客户登陆
1 前台系统客户注册功能 页面:signup.html 1.1 验证手机号是否注册(邮箱同样) 1. 使用Jquery-validate插件进行相关校验,使用校验规则 <input type=& ...
- dedecms织梦系统后台验证码图片不显示的解决方法
网站迁移后,dedecms织梦系统后台验证码图片不显示的解决方法通用解决方案-取消后台验证码功能因为没有验证码,不能进后台,所以修改php文件源代码:方法一:打开dede/login.php 找到如下 ...
- 潭州课堂25班:Ph201805201 django 项目 第九课 图片验证码前台实现,判断用户是否注册功能实现 (课堂笔记)
u胎代码实现 : 针对每一个 app 写个 js 脚本, 先给 users 的 app 应用创建个 js:在指定目录下的 js 文件夹下,创建 users 文件夹,下创建 suth.js ,图片验证 ...
- Webform 文件上传、 C#加图片水印 、 图片验证码
文件上传:要使用控件 - FileUpload 1.如何判断是否选中文件? FileUpload.FileName - 选中文件的文件名,如果长度不大于0,那么说明没选中任何文件 js - f.val ...
- 字符型图片验证码识别完整过程及Python实现
字符型图片验证码识别完整过程及Python实现 1 摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...
- webform(十)——图片水印和图片验证码
两者都需要引入命名空间:using System.Drawing; 一.图片水印 前台Photoshuiyin.aspx代码: <div> <asp:FileUpload ID=&q ...
- php 图片验证码生成 前后台验证
自己从前一段时间做了个php小项目,关于生成图片验证码生成和后台的验证,把自己用到的东西总结一下,希望大家在用到相关问题的时候可以有一定的参考性. 首先,php验证码生成. 代码如下: 1.生成图像代 ...
- ASP.NET MVC 模块与组件(二)——定制图片验证码
本着简洁直接,我们就直奔主题吧! 下面是一个生成数字和字母随机组合的验证码类源代码: using System; using System.Drawing; using System.Drawing ...
随机推荐
- Android4.0新增的网格布局
网格布局由GridLayout代表,它是Android 4.0新增的布局管理器,因此需要在Android 4.0 之后的版本中才能使用该布局管理器.如果希望在更早的Android平台上使用该布局管理器 ...
- MVC使用HandleErrorAttribute自定义异常
MVC中,有一个Filter可以捕捉错误,但是它的用法是利用Attribute来实现的,而且只能加在Controller和Action上,所以不能捕捉别出的错误 其实理论上所有的错误肯定产生于Cont ...
- 使用AngularJS的三个重要原因
入门教程:http://www.ituring.com.cn/minibook/303 : http://angularjs.cn/tag/AngularJS 原因一:Google开发的框架 要知道开 ...
- HoloLens开发手记 - 开始使用Vuforia Getting started with Vuforia
Vuforia在6.1版本的Unity SDK里实现了对HoloLens的支持. 查看 Developing for Windows 10 in Unity 这篇文章来了解如何配置Unity和Visu ...
- iOS-如何使用symbolicatecrash
iOS-如何使用symbolicatecrash 如何使用symbolicatecrash工具分析iOS Crash文件: 原文地址:[iOS Crash文件分析]-如何使用symbolicatecr ...
- secache 详解
介绍下secache缓存,它是属于文件缓存.简单来说,文件缓存就是把缓存数据存储到文件系统 (硬盘)中了,比 内存缓存要慢一些,但是也是有一点优点的. 1.磁盘容量大, 2保存到硬盘,说明 掉电后数据 ...
- opp(Object Oriented Programming)
嗯,昨天忙了一天没来及发,过年啊,打扫啊,什么搽窗户啊,拖地啊,整理柜子啊,什么乱七八糟的都有,就是一个字,忙. 好了,废话也不多说,把自己学到的放上来吧.嗯,说什么好呢,就说原型链啊 原型对象 每个 ...
- json-lib之复杂数据类型的转换
在json字符串转java bean时,一般的对象,可以直接转,如:一个学生类,属性有姓名.年龄等 public class Student{ private String sname; privat ...
- [CSS3] 学习笔记--CSS盒子模型
1.CSS盒子模型概述 盒子模型的内容范围包括:margin(外边距).border(边框).padding(内边距).content(内容)部分组成. 2.内边距 内边距在content外,bord ...
- 属性——AddComponentMenu
字面理解:添加 组件选项菜单 分析:可能是添加一个脚本或者组件到一个物体上 验证: 新建一个脚本:AttributeTest 提示:添加一个组件菜单属性,允许你放一个脚本在Compoent菜单下,来代 ...