背景: 因为移动端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---前台系统图片验证码心得的更多相关文章

  1. Django实战(一)-----用户登录与注册系统5(图片验证码)

    为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是一种区分用户是计算机还是人的公共全自动程序. 可以防止恶意破解密码.刷票.论坛 ...

  2. 项目一:第八天 1、前台系统导入 实现客户注册 发验证码,邮件 springdata-redis存储数据 3、实现客户登陆

    1 前台系统客户注册功能 页面:signup.html 1.1 验证手机号是否注册(邮箱同样) 1. 使用Jquery-validate插件进行相关校验,使用校验规则 <input type=& ...

  3. dedecms织梦系统后台验证码图片不显示的解决方法

    网站迁移后,dedecms织梦系统后台验证码图片不显示的解决方法通用解决方案-取消后台验证码功能因为没有验证码,不能进后台,所以修改php文件源代码:方法一:打开dede/login.php 找到如下 ...

  4. 潭州课堂25班:Ph201805201 django 项目 第九课 图片验证码前台实现,判断用户是否注册功能实现 (课堂笔记)

    u胎代码实现 : 针对每一个 app 写个 js 脚本, 先给 users 的 app 应用创建个 js:在指定目录下的 js 文件夹下,创建 users 文件夹,下创建 suth.js ,图片验证 ...

  5. Webform 文件上传、 C#加图片水印 、 图片验证码

    文件上传:要使用控件 - FileUpload 1.如何判断是否选中文件? FileUpload.FileName - 选中文件的文件名,如果长度不大于0,那么说明没选中任何文件 js - f.val ...

  6. 字符型图片验证码识别完整过程及Python实现

    字符型图片验证码识别完整过程及Python实现 1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...

  7. webform(十)——图片水印和图片验证码

    两者都需要引入命名空间:using System.Drawing; 一.图片水印 前台Photoshuiyin.aspx代码: <div> <asp:FileUpload ID=&q ...

  8. php 图片验证码生成 前后台验证

    自己从前一段时间做了个php小项目,关于生成图片验证码生成和后台的验证,把自己用到的东西总结一下,希望大家在用到相关问题的时候可以有一定的参考性. 首先,php验证码生成. 代码如下: 1.生成图像代 ...

  9. ASP.NET MVC 模块与组件(二)——定制图片验证码

     本着简洁直接,我们就直奔主题吧! 下面是一个生成数字和字母随机组合的验证码类源代码: using System; using System.Drawing; using System.Drawing ...

随机推荐

  1. delphi下实现控制其它窗体中的控件代码模板(delphi 7安装程序)

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  2. QT第五天学习

    回顾: QFile QTextSream QDataSream QFileInfo QDir Dir entryList 返回目录下所有文件和目录的名字 entryInfoList 返回目录下所有文件 ...

  3. --@angularJS--自定义服务与后台数据交互小实例

    1.myService.html: <!DOCTYPE HTML><html ng-app="app"><head>    <title& ...

  4. 关于P,NP,NPC和NP-hard的通俗解释

    这些概念以前老是犯糊涂,今天整清楚.摘要:P: Polynomial SolvableNP: Non-determinstic Polynomial Solvable 0)词语解释:Polynomia ...

  5. CSS 简介、语法、派生选择器、id 选择器、类选择器、属性选择器

    CSS 概述 CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表中 把样式添加到 HTML 4.0 中,是为了解决内容与表现 ...

  6. Quercus

    其实,我不确定Quercus是否可以被认定为一门JVM语言:其次Quercus这个东东分开源版与商业版,开源版只能解释执行.而商业版能编译成Java字节码. 但我知道国内,阿里巴巴很早就在使用它,当然 ...

  7. CodeForces 722A

    A. Broken Clock time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

  8. HDU5692(线段树+dfs序)

    Snacks Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  9. [html] 学习笔记-Canvas图形绘制处理

    使用Canvas API 可以将一个图形重叠绘制在另外一个图形上,也可以给图形添加阴影效果. 1.Canvas 图形组合 通过 globalCompositeOperation = 属性 来指定重叠效 ...

  10. Bootstrap WPF Style(二)--Glyphicons 字体图标

    介绍 关于Glyphicons字体图标,首先给出友情链接 Glyphicons 这个项目是在Bootstrap WPF Style项目基础上做的,详见http://www.cnblogs.com/ts ...