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 ...
随机推荐
- 1.2.Core Data 的适用场合(Core Data 应用程序实践指南)
如果应用程序要保存的设置数据太多,以致NSUserDefaults及“属性列表“(property list)这种简单的存储方案无法应付.不需要再"重新发明轮子"(reinvent ...
- 在Cocos2d-x中实现较为真实的云彩效果
[前言] 这个效果是公司里上一个项目中用到的.因为项目已经死掉了,并且效果是我自己实现的,与其连着项目工程一起删掉,不如所以共产主义一下给大家作参考. 使用版本:cocos 2d-x 3.6(适用于所 ...
- php如何判断是手机访问还是电脑访问
<?php function isMobile(){ $useragent=isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AG ...
- cygwin下配置alias
主要是cygwin下的盘符映射关系容易忘,直接用mount命令: 所以,找到E:\cygwin64\home\Administrator下面的.bashrc,添加alias.如下:
- Android的文件存储
//文件的写入 String content1 = edt_file.getText().toString(); //用于文件的写操作 FileOutputStream fos=null; //缓冲输 ...
- WinForm TextBox 实现自动索引功能
源代码如下: http://pan.baidu.com/s/1bnOz4hp
- CSS页面渲染优化属性will-change
前面的话 当我们通过某些行为(点击.移动或滚动)触发页面进行大面积绘制的时候,浏览器往往是没有准备的,只能被动使用CPU去计算与重绘,由于没有事先准备,应付渲染够呛,于是掉帧卡顿.而CSS属性wi ...
- vue.js中ajax请求
<div id="app"> <table style="border-collapse: collapse"> <thead&g ...
- [转载] HTTP协议详解
转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...
- C# out的使用 函数例题
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...