.net点选验证码实现思路分享

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

先上效果图

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

贴代码前先说点思路:

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=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://pan.baidu.com/s/1eS5Mn30 密码:7iud

分享代码改变世界

时间: 2024-10-08 10:08:54

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

关于Exchange Server 2010 公网发布思路分享

最近在论谈中经常会看到关于Exchange Server 2010映射完成后,如何保证可于外网进行正常邮件投递的咨询,我在这里也就Exchange Server 2010公网发布之前总结的一些思路进行一下分享,其实最好的办法是,在你准备与网络工程师沟通发布时,先自己在内部进行一次测试,测试方法也很简单,如下:           1.搭建另一个测试域,其中包括AD.证书.邮件全部功能. 2.保证测试域与即将上线的生产域之间可正常进行邮件投递收发. 接下来,需要准备一份如下图所示的表单,来告诉网络

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

借用UAC完成的提权思路分享 背景 UAC(User Account Control,用户帐户控制)是微软为提高系统安全而在Windows Vista中引入的新技术,它要求用户在执行可能会影响计算机运行的操作或执行更改影响其他用户的设置的操作之前,提供权限或管理员‌密码. 也就是说一旦用户允许启动的应用程序通过UAC验证,那么这个程序也就有了管理员权限.如果我们通过某种方式劫持了通过用户UAC验证的程序,那么相应的我们的程序也就实现了提权的过程. 提权过程概述 首先我们找到目标程序,查找其动态加

会员管理系统的设计和开发(3)--主界面的设计思路分享

会员管理系统经过一段时间的紧锣密鼓开发,软件终于完成并发布.在这期间,碰到了不少技术难点,并积累了不少开发心得和经验,本篇继续介绍这个开发过程中相关的技术要点,本章主要介绍会员管理里面,列表主界面的一些设计思路分享. 有时候,遵循一些固定的套路做事情,总是很容易,如果每个地方搞一些创新和改进,那么往往需要花费很多时间,但是创新是有积极意义的,虽然可能会遇到困难,但是很值得去做.在Winform的界面设计上,虽然我可以使用代码生成工具生成比较标准的界面了,但是我总是喜欢参考学习,并改进一些界面方面

渗透测试一些思路分享

渗透测试一些思路分享 (1)  收集网站信息 首先确定网站采用何种语言编写.或者是否有混用的情况.此处可以通过查看网站源文件,观察网站链接,捕获提交请求等方式获取. (2)  爬行网站目录 使用工具对网站目录进行爬行,可以辅助上一步让结果更加精准.将爬行结果存档,如果可以,此处应分析出网站是否使用通用程序,如果是,记录下来.进行下一步. (3)  暴力目录探测 根据上一步的爬行结果,对网站根目录或者关键目录进行暴力目录探测,如果网站为通用程序,判读是否有过二次开发,如非通用程序,在探测到的目录中

HyperLedger Fabric 学习思路分享

HyperLedger Fabric 学习思路分享 HyperLedger Fabric最初是由Digital Asset和IBM公司贡献的.由Linux基金会主办的一个超级账本项目,它是一个目前非常流行并广为人知的区块链网络框架的实现方案.作为一种基于模块化架构开发应用程序或解决方案的基础,HyperLedger Fabric支持如共识和会员服务等即插即用的组件,它的设计初衷是支持不同组件的可插拔实现,并适应整个经济生态系统的复杂性和高精度性.HyperLedger Fabric利用容器技术运

网易易盾行为式验证码家族添新成员:图标点选验证码上线 尤适出海企业

近日,网易易盾行为式验证码家族迎来一位新的成员--图标点选验证码,在提供高安全性.国际化的同时,又更加通用化,适合出海企业和服务于低龄端的产品应用.左为文字点选式验证码,右为图标点选式验证码 在图标点选式验证码使用上,用户只要根据提示,按照顺序点击图中图标,即可完成验证.相较文字点选式验证码,它更加通用化,非中文用户也可以轻松识别完成验证. 图标点选式验证码开发原理与传统验证码不同,主要是通过收集用户的行为轨迹信息.设备信息等,作为人机判别依据. 不同于文字点选,由于图标元素周期性叠代更新,再加

验证码解决思路

验证码问题解决思路1.识别,python当中提供了一部分图片验证码识别的库,成功率有限,调用别人免费的api接口2.万能验证码: 开发同学提供的,缺点是:开发有工作量,到生产环境这个逻辑需要去掉3.Debug: 手工输入后,再执行代码点击登陆,缺点:不能持续集成4.到数据库中拿:验证码生成逻辑,后端有一个算法,生成验证码,保存后,传给前端,前端展示,保存的位置:redis: 自己维护过期时间 推荐,测试同学就到这个redis中读一下这个验证码就可以了图片也是数据的一种,它在数据中就是一个字符串,

taobao 爬虫基本思路分享

taobao 爬虫基本思路分享原创置顶 yellowhatgood 最后发布于2016-08-17 17:39:58 阅读数 7236 收藏展开   关于taobao 爬取 下面做一个分享,大家一起研究 1. taobao, tmall 店铺数据                     在官网上我们可以通过 search 接口 (https://shopsearch.taobao.com/search?app=shopsearch&q=iphone )获取前 1020 页数据,界面展示是 100

Python3网络爬虫实战-44、点触点选验证码的识别

上一节我们实现了极验验证码的识别,但是除了极验其实还有另一种常见的且应用广泛的验证码,比较有代表性的就是点触验证码. 可能你对这个名字比较陌生,但是肯定见过类似的验证码,比如 12306,这就是一种典型的点触验证码,如图 8-18 所示: 图 8-18 12306 验证码 我们需要直接点击图中符合要求的图,如果所有答案均正确才会验证成功,如果有一个答案错误,验证就会失败,这种验证码就可以称之为点触验证码.学习过程中有不懂的可以加入我们的学习交流秋秋圈784中间758后面214,与你分享Pytho