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

先上效果图

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

贴代码前先说点思路:

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. C语言 · 高精度加法

    问题描述 输入两个整数a和b,输出这两个整数的和.a和b都不超过100位. 算法描述 由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储.对于这种问题,一般使用数组来处理. 定义一个数组A ...

  2. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  3. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  4. C语言 · 矩阵乘法 · 算法训练

    问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j ...

  5. Java多线程基础——对象及变量并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  6. Ubuntu 16.10 安装KolourPaint 4画图工具

    KolourPaint 4画图工具简单实用,可以绘画.视频处理和图标编辑: • 绘画:绘制图表和“手绘” • 视频处理:编辑截图和照片;应用特效 • 图标编辑:绘画剪贴和标识透明化 1.在Ubuntu ...

  7. 前端学HTTP之内容协商

    前面的话 一个URL常常需要代表若干不同的资源.例如那种需要以多种语言提供其内容的网站站点.如果某个站点有说法语的和说英语的两种用户,它可能想用这两种语言提供网站站点信息.理想情况下,服务器应当向英语 ...

  8. Mac上MySQL忘记root密码且没有权限的处理办法&workbench的一些tips (转)

    忘记Root密码肿么办 Mac上安装MySQL就不多说了,去mysql的官网上下载最新的mysql包以及workbench,先安装哪个影响都不大.如果你是第一次安装,在mysql安装完成之后,会弹出来 ...

  9. HTML+CSS 项目总结

    在过去的大概一个月的学习,基本掌握了HTML+CSS的用法和特性. 这个星期老师给我们布置了一个PC端的实战项目,并且要求在3-4天内完成,我不惜废寝忘食,在紧迫的时间内大致地完成了,但是有些效果不能 ...

  10. JavaScript基础学习-函数及作用域

    函数和作用域是JavaScript的重要组成部分,我们在使用JavaScript编写程序的过程中经常要用到这两部分内容,作为初学者,我经常有困惑,借助写此博文来巩固下之前学习的内容. (一)JavaS ...