哈哈好久没冒泡了,最进看见点选验证码有点意思,所以想自己写一个。
先上效果图
如果你被这个效果吸引了就请继续看下去。
贴代码前先说点思路:
1.要有一个汉字库,并按字形分类。(我在数据库里是安部首分类的)
2.获取验证码(也就是取几个文字做验证码)
3.根据取出来的文字去找形近字
4.排列验证码文字和形近字
5.绘制图片
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=1) { 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 < 9) { var ran = new Random(); var randKey = ran.Next(0, 4); var item = wenzlist[randKey]; var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID, 9 - 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 + 1), item); } return newList; }
五、绘制图片
下面是画图的代码,验证码和备选答案对应两种不同的画法(里面注释写的还算清楚)。不要担心文字旋转x°后人类分不出来,哈哈。代码最后一句我把图片转成了Base64,方便前端调用。
private static string GetImage(string text) { Image image; switch (text.Length) { case 1: image = new Bitmap(50, 40); break; case 4: image = new Bitmap(120, 40); break; default: image = new Bitmap(50, 40); break; } Brush brushText = new SolidBrush(Color.FromArgb(255, 0, 0, 0)); var graphics = Graphics.FromImage(image); graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.Clear(Color.White); var font = new Font(new FontFamily("华文彩云"), 20, FontStyle.Regular); if (text.Length > 1)//画验证码 { //先来两条直线做干扰 然后再画文字 graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(0, 10), new Random().Next(10, 40)), new Point(new Random().Next(100, 120), new Random().Next(10, 30))); graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(20, 50), new Random().Next(0, 10)), new Point(new Random().Next(100, 120), new Random().Next(30, 40))); graphics.DrawString(text, font, brushText, 0, 10); } else//画备选答案 { Point middle = new Point(25, 20); graphics.TranslateTransform(middle.X, middle.Y); //这里是360°随机旋转 graphics.RotateTransform(new Random().Next(0, 360)); var format = new StringFormat(StringFormatFlags.NoClip) { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; graphics.DrawString(text, font, brushText, 0, 0, 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://xiazai.jb51.net/201701/yuanma/VerificationCode_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍12306验证码破解思路分享,包括了12306验证码破解思路分享的使用技巧和注意事项,需要的朋友参考一下 一个12306验证码破解思路, 图片采集 + 概率 //分析: 1. 单次验证码里面有8个图片,类型最多8种,最少不太确定 2. 8个图是规则排列,可以很容易分隔 3. 图片库应该是有限的,可以采集,计算hash入库,这里需要关联相同类型图片 (比如 “杯子”,“刷子”等) 备
本文向大家介绍ASP.NET实现的生成验证码功能示例【附demo源码】,包括了ASP.NET实现的生成验证码功能示例【附demo源码】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了ASP.NET实现的生成验证码功能。分享给大家供大家参考,具体如下: 生成验证码原理:产生随机字符,并将字符生成为图片,同时储存到Session里去,然后验证用户输入的内容是否与Session中的验证码相符即可
本文向大家介绍详解iOS 验证码输入的实现思路,包括了详解iOS 验证码输入的实现思路的使用技巧和注意事项,需要的朋友参考一下 如图所示,现在很多App采用了类似下划线、方块等方式的验证码输入,直观美观!对于这种效果的实现方式,大概有以下几种方式: 1.多个UITextField组成 这种方式好处是有光标闪烁、但是在处理删除和动画效果时,就会显得有点笨拙,OFO应该是这样实现的,要严格处理好每个U
本文向大家介绍SpringBoot实现短信验证码校验方法思路详解,包括了SpringBoot实现短信验证码校验方法思路详解的使用技巧和注意事项,需要的朋友参考一下 有关阿里云通信短信服务验证码的发送,请参考我的另一篇文章 Springboot实现阿里云通信短信服务有关短信验证码的发送功能 思路 用户输入手机号后,点击按钮获取验证码。并设置冷却时间,防止用户频繁点击。 后台生成验证码并发送到用户
本文向大家介绍Java实现身份证号码验证源码示例分享,包括了Java实现身份证号码验证源码示例分享的使用技巧和注意事项,需要的朋友参考一下 整理文档,搜刮出一个Java实现身份证号码验证源码示例代码,稍微整理精简一下做下分享。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍asp.net登录验证码实现方法,包括了asp.net登录验证码实现方法的使用技巧和注意事项,需要的朋友参考一下 前端添加的标签和方法: 验证码: 然后在项目中在新建一个VerifyCode.aspx,下面是aspx的代码: 接着是aspx.cs的代码: 于是!就可以生成验证码了,然后自己再把编写验证版的判断逻辑写好就可以啦! 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望