哈哈好久没冒泡了,最进看见点选验证码有点意思,所以想自己写一个。

先上效果图

如果你被这个效果吸引了就请继续看下去。

贴代码前先说点思路:

1.要有一个汉字库,并按字形分类。(我在数据库里是安部首分类的)

2.获取验证码(也就是取几个文字做验证码)

3.根据取出来的文字去找形近字

4.排列验证码文字和形近字

5.绘制图片

6.显示

6.写个博客分享一下(分享代码改变世界)

一、获取字库

  我国文化博大精深,辣么多的字从哪儿来?当然我不可能手动加进去,于是我就在网上随便找了一个能查汉字的网站,去抓别人的数据。抓数据的方法请点传送门。传送门里说的只是思路,如果有不明白的请艾特我。我会在下面共享我的字库。

二、获取验证码

这个就比较简单了这里我就直接贴代码了,下面的代码就是随机排序后取4条数据,我这样写是为了图方便。个人觉得先随机生成ID,然后直接根据ID取数据,这样查询速度会比下面这种写法快。(注意我用的数据库是MySql)

        /// <summary>
/// 获取验证码
/// </summary>
public List<VerificationCode.Model.WenZhi> GetCodeText()
{
const string sql = "SELECT * FROM wenzhi ORDER BY RAND() LIMIT 4";
var dataReader = dbHelper.GetDataReader(sql);
var list = DataReaderToList(dataReader);
dataReader.Close();
return list;
}

三、根据取出来的文字去找形近字

  因为第一步的时候我存部首了,所以这里我直接根据部首取获取当前部首的形近字。

        /// <summary>
/// 获取答案备选
/// </summary>
/// <param name="buShouCode">部首编码</param>
/// <param name="id">当前文字ID</param>
/// <param name="number">数量</param>
/// <returns></returns>
public List<VerificationCode.Model.WenZhi> GetAnswer(string buShouCode, int id,int number=)
{
string sql = $"SELECT * FROM wenzhi where BuShouCode='{buShouCode}' and ID <> {id} ORDER BY RAND() LIMIT "+ number;
var dataReader = dbHelper.GetDataReader(sql);
var list = DataReaderToList(dataReader);
dataReader.Close();
return list;
}

四.排列验证码文字和形近字

  下面的代码是先把备选答案和验证码放在一个集合里然后再对集合排序

 public Model.Code GetCode()
{ var wenzlist = _wenZhiDal.GetCodeText(); //获取验证码
var listAnsuwr = new List<Answer>();//实例化备选答案对象
var answerCode = string.Empty;//答案
var result = new Model.Code
{
Id = Guid.NewGuid().ToString()
};
//根据验证码获取备选答案并把添加到答案添加到备选答案集合
foreach (var item in wenzlist)
{
answerCode += item.ID + ",";
result.AnswerValue += item.Text;
var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID);
listAnsuwr.Add(new Answer { Id = item.ID.ToString(), Img = GetImage(item.Text) });
listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
}
//如果答案个数不够就再去取几个
if (listAnsuwr.Count < )
{
var ran = new Random();
var randKey = ran.Next(, );
var item = wenzlist[randKey];
var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID, - listAnsuwr.Count);
listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
}
result.CodeImg = GetImage(result.AnswerValue);//获取图片
result.AnswerValue = answerCode.TrimEnd(',');
result.Answer = RandomSortList(listAnsuwr);//打乱正确答案与形近字的顺序
return result;
}

这是对集合排序的代码

        /// <summary>
/// 随机排列集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="listT"></param>
/// <returns></returns>
private static List<T> RandomSortList<T>(IEnumerable<T> listT)
{
var random = new Random();
var newList = new List<T>();
foreach (var item in listT)
{
newList.Insert(random.Next(newList.Count + ), item);
}
return newList;
}

五、绘制图片

下面是画图的代码,验证码和备选答案对应两种不同的画法(里面注释写的还算清楚)。不要担心文字旋转x°后人类分不出来,哈哈。代码最后一句我把图片转成了Base64,方便前端调用。

private static string GetImage(string text)
{
Image image;
switch (text.Length)
{
case :
image = new Bitmap(, );
break;
case :
image = new Bitmap(, );
break;
default:
image = new Bitmap(, );
break;
}
Brush brushText = new SolidBrush(Color.FromArgb(, , , ));
var graphics = Graphics.FromImage(image);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.Clear(Color.White);
var font = new Font(new FontFamily("华文彩云"), , FontStyle.Regular);
if (text.Length > )//画验证码
{
//先来两条直线做干扰 然后再画文字
graphics.DrawLine(new Pen(brushText, new Random().Next(, )), new Point(new Random().Next(, ), new Random().Next(, )), new Point(new Random().Next(, ), new Random().Next(, )));
graphics.DrawLine(new Pen(brushText, new Random().Next(, )), new Point(new Random().Next(, ), new Random().Next(, )), new Point(new Random().Next(, ), new Random().Next(, )));
graphics.DrawString(text, font, brushText, , ); }
else//画备选答案
{
Point middle = new Point(, );
graphics.TranslateTransform(middle.X, middle.Y);
//这里是360°随机旋转
graphics.RotateTransform(new Random().Next(, ));
var format = new StringFormat(StringFormatFlags.NoClip)
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
graphics.DrawString(text, font, brushText, , , format); }
brushText.Dispose();
graphics.Dispose();
return ImageToBase64(image);
}

六、显示

直接调用GetCode方法就能返回验证码对象

下面是后台代码,应为正确答案是放在AnswerValue里的所以我先把取出来放Session里面,然后把值清空后再通过json返回给浏览器。

        public string GetVerCode()
{
var code = new VerificationCode.Code().GetCode();
Session["VERCODE"] = code.AnswerValue;
code.AnswerValue = "";
return JsonConvert.SerializeObject(code);
}

现在来堆点html代码

<div class="form-group">
<ul class="vercode">
<li><img src=''/></li>
<li><img src=''/></li>
<li><img src=''/></li>
<li><img src=''/></li>
<li class="delete" onclick="delete_input()"></li>
</ul>
<div>
<img id="code-image"/> <a href="javascript:void(0);" onclick="load_vercode()">看不清?</a>
</div>
<ul class="vercode-anwser">
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
</ul>
</div>

再来点js代码,这里只实现的图片上的效果,还没对数据验证(这里说说验证思路:每个图片对应一个ID,取到选择图片的ID用逗号分隔,然后与Session里的值对比)

<script>
$(function () {
//加载验证码
load_vercode();
//绑定验证码点击事件
$(".vercode-anwser").find("img").on("click", null, function () {
$(".vercode").find("img[src='']:eq(0)").attr("src", $(this).attr("src"));
});
}); function load_vercode() {
$(".vercode").find("img").attr("src", "");
$.get("GetVerCode", function (data) {
var result = JSON.parse(data);
$("#code-image").attr("src", "data:image/png;base64," + result.CodeImg);
$(".vercode-anwser").find("img").each(function (index) {
$(this).attr("src", "data:image/png;base64," + result.Answer[index].Img);
});
});
}
//删除事件
function delete_input() {
$(".vercode").find("img[src!='']:last").attr("src", "");
}
</script>

到这里代码就差不多了,以上思路只是单纯的个人想法,有兴趣的朋友一起来讨论吧。

源代码在这里-->地址 http://pan.baidu.com/s/1eS5Mn30 密码:7iud

分享代码改变世界

.net点选验证码实现思路分享的更多相关文章

  1. HyperLedger Fabric 学习思路分享

    HyperLedger Fabric 学习思路分享 HyperLedger Fabric最初是由Digital Asset和IBM公司贡献的.由Linux基金会主办的一个超级账本项目,它是一个目前非常 ...

  2. [技术分享]借用UAC完成的提权思路分享

    借用UAC完成的提权思路分享 背景 UAC(User Account Control,用户帐户控制)是微软为提高系统安全而在Windows Vista中引入的新技术,它要求用户在执行可能会影响计算机运 ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享

    今天这篇博文的主要目的是分享一下我设计Saga的实现思路来抛砖引玉,其实Saga本身非常的类似于一个简单的工作流体系,相比工作流不一样的部分在于它没有工作流的复杂逻辑处理机制(比如会签),没有条件分支 ...

  4. 开源图编辑库 NebulaGraph VEditor 的设计思路分享

    本文首发于 NebulaGraph 公众号 NebulaGraph VEditor 是一个拥有高性能.高可定制的所见即所得图可视化编辑器前端库. NebulaGraph VEditor 底层基于 SV ...

  5. openvpn通过ldap或ad统一认证解决方案思路分享

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/986933 缘起:成 ...

  6. Vue的全选功能实现思路

    全选功能的实现主要分两步: 1. 点击全选框选中所有选择框. 2. 当所有选择框都被选中时,勾选全选框. 详细思路: 1. 点击全选框选中所有选择框: 给全选框绑定一个值,然后添加change时间,当 ...

  7. 通过JS逆向ProtoBuf 反反爬思路分享

    前言 本文意在记录,在爬虫过程中,我首次遇到Protobuf时的一系列问题和解决问题的思路. 文章编写遵循当时工作的思路,优点:非常详细,缺点:文字冗长,描述不准确 protobuf用在前后端传输,在 ...

  8. 技术分享 | Update更新慢、死锁等问题的排查思路分享

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 一.简介 在开始排错之前我们需要知道 Update 在 MySQL 中的生命周期 ...

  9. PHP编写的图片验证码类文件分享方法

    适用于自定义的验证码类! <?php/* * To change this license header, choose License Headers in Project Propertie ...

随机推荐

  1. jQuery之ajax实现篇

    jQuery的ajax方法非常好用,这么好的东西,你想拥有一个属于自己的ajax么?接下来,我们来自己做一个简单的ajax吧. 实现功能 由于jq中的ajax方法是用了内置的deferred模块,是P ...

  2. python自动化测试(2)-自动化基本技术原理

    python自动化测试(2) 自动化基本技术原理 1   概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...

  3. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  4. 游戏服务器菜鸟之C#初探一游戏服务

    本人80后程序猿一枚,原来搞过C++/Java/C#,因为工作原因最后选择一直从事C#开发,因为读书时候对游戏一直比较感兴趣,机缘巧合公司做一个手游的项目,我就开始游戏服务器的折腾之旅. 游戏的构架是 ...

  5. 利用bootstrap的carousel.js实现轮播图动画

    前期准备: 1.jquery.js. 2.bootstrap的carousel.js. 3.bootstrap.css. 如果大家不知道在哪下载,可以联系小颖,小颖把这些js和css可以发送给你. 一 ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(69)-微信公众平台开发-功能概述

    系列目录 为什么要先发这个文章? 因为接下来的文章是关于微信开发的系列,心中一定要有一个概念,知道自己接下来要做什么功能. 而且微信到处都是坑,我首先要把微信与本地跑通起来才敢发布,否则中间出现坑导致 ...

  7. 在Asp.Net中操作PDF – iTextSharp - 使用表格

    使用Asp.Net生成PDF最常用的元素应该是表格,表格可以帮助比如订单或者发票类型的文档更加格式化和美观.本篇文章并不会深入探讨表格,仅仅是提供一个使用iTextSharp生成表格的方法介绍 使用i ...

  8. 你真的会玩SQL吗?之逻辑查询处理阶段

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  9. 要想提高PHP的编程效率,你必须知道的要点

    1.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数.此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储 ...

  10. 游戏AI系列内容 咋样才能做个有意思的AI呢

    游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...