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 ...
随机推荐
- delphi下实现控制其它窗体中的控件代码模板(delphi 7安装程序)
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- QT第五天学习
回顾: QFile QTextSream QDataSream QFileInfo QDir Dir entryList 返回目录下所有文件和目录的名字 entryInfoList 返回目录下所有文件 ...
- --@angularJS--自定义服务与后台数据交互小实例
1.myService.html: <!DOCTYPE HTML><html ng-app="app"><head> <title& ...
- 关于P,NP,NPC和NP-hard的通俗解释
这些概念以前老是犯糊涂,今天整清楚.摘要:P: Polynomial SolvableNP: Non-determinstic Polynomial Solvable 0)词语解释:Polynomia ...
- CSS 简介、语法、派生选择器、id 选择器、类选择器、属性选择器
CSS 概述 CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表中 把样式添加到 HTML 4.0 中,是为了解决内容与表现 ...
- Quercus
其实,我不确定Quercus是否可以被认定为一门JVM语言:其次Quercus这个东东分开源版与商业版,开源版只能解释执行.而商业版能编译成Java字节码. 但我知道国内,阿里巴巴很早就在使用它,当然 ...
- CodeForces 722A
A. Broken Clock time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- HDU5692(线段树+dfs序)
Snacks Time Limit:5000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- [html] 学习笔记-Canvas图形绘制处理
使用Canvas API 可以将一个图形重叠绘制在另外一个图形上,也可以给图形添加阴影效果. 1.Canvas 图形组合 通过 globalCompositeOperation = 属性 来指定重叠效 ...
- Bootstrap WPF Style(二)--Glyphicons 字体图标
介绍 关于Glyphicons字体图标,首先给出友情链接 Glyphicons 这个项目是在Bootstrap WPF Style项目基础上做的,详见http://www.cnblogs.com/ts ...