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

news2024/11/16 3:47:52

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

先上效果图

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

贴代码前先说点思路:

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://www.coloradmin.cn/o/682994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣题库刷题笔记13--罗马数字转整数

1、题目如下&#xff1a; 2、个人Python代码实现&#xff1a; 虽然前面刚刷了整数转罗马数字&#xff0c;而且本题难度为简单&#xff0c;实际上做出来还是花了很多时间&#xff0c;不亚于前面整数转罗马数字。 以上的思路&#xff0c;主要是声明一个列表temp&#xff0c;然后遍…

【MYSQL】—— MySQL 在 Centos 7环境安装

本期&#xff0c;我将给大家介绍的是如何在【Linux】上安装相应的 mysql。 目录 1. 卸载不要的环境 2. 检查系统安装包 3. 获取mysql官⽅yum源 4. 安装mysql yum 源&#xff0c;对⽐前后yum源 5. 看看能不能正常⼯作 6. 安装mysql服务 7. 启动服务 8. 查看启动服务 9.…

从“特种兵旅游”到“citywalk”,渡远户外还能热下去么?

过去风靡一时的“户外露营热”&#xff0c;有些企业赶上了&#xff0c;有些没有。去年坐上“末班车”的渡远户外也想尝些甜头。 套上“户外”概念的渡远户外&#xff0c;或许正在被质疑“血统”并不“纯正”&#xff0c;主营房车游艇配套产品和水上休闲运动产品&#xff0c;说…

【新星计划Linux】——学习工具VMware介绍

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 前言 本章将会讲解Linux学习工具VMware介绍。 一.VMware介绍 1.前期准备 官方网站&#…

【资料分享】全志科技T507-H评估板规格书(4核ARM Cortex-A53,主频1.416GHz)

1 评估板简介 创龙科技TLT507-EVM是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53国产工业评估板&#xff0c;主频高达1.416GHz&#xff0c;由核心板和评估底板组成。核心板CPU、ROM、RAM、电源、晶振等所有器件均采用国产工业级方案&#xff0c;国产化率100%。同时&a…

实战:win10安装docker并用docker-compose构建运行容器

文章目录 前言Docker DesktopHyper-V安装 Docker Desktop for Windows下载docker desktopDocker安装目录软连接运行Docker Desktop安装文件Docker Desktop验证 docker-compose构建运行管理容器创建文件目录及配置文件构建并启动容器查看启动的容器并验证 写在最后 前言 Docker…

数字IC前端学习笔记:仲裁轮询(四)

相关文章 数字IC前端学习笔记&#xff1a;LSFR&#xff08;线性反馈移位寄存器&#xff09; 数字IC前端学习笔记&#xff1a;跨时钟域信号同步 数字IC前端学习笔记&#xff1a;信号同步和边沿检测 数字IC前端学习笔记&#xff1a;锁存器Latch的综合 数字IC前端学习笔记&am…

网络安全|渗透测试入门学习,从零基础入门到精通—动态分析技术工具OllyDbg界面介绍

目录 动态分析技术调试器 什么是OllyDbg OllyDbg能干什么 OllyDbg窗口介绍 1、反汇编面板窗口 2、信息面板窗口 3、数据面板窗口 4、寄存器面板窗口 5、栈面板窗口 动态分析技术调试器 动态分析技术中最重要的工具是调试器&#xff0c;分为用户模式和内核模式两种类型…

【c++11】万能引用和完美转发

c11 万能引用完美转发 这一节是对上一篇右值引用的补充。 链接: 右值引用 万能引用 看如下代码 void Fun(int &x){ cout << "左值引用" << endl; } void Fun(const int &x){ cout << "const 左值引用" << endl; }void …

推荐四款常用在档案室温湿度记录的传感器记录仪

A.数字信号485信号输出的温湿度传感器/变送器 主要参数 液晶显示、485信号输出、9-24/VDC供电、壁挂式安装/吸顶式安装、走线/连接方式485总线、标准modbus RTU通讯协议 B。数字信号RJ45信号输出的温湿度传感器/变送器 ​主要参数 液晶显示、RJ45信号输出、9-24/VDC供电/标…

Zabbix Timeout 设置不当导致的问题

哈喽大家好&#xff0c;我是咸鱼 今天跟大家分享一个关于 zabbix Timeout 值设置不当导致的问题&#xff0c;这个问题不知道大家有没有碰到过 问题 事情经过是这样的&#xff1a; 把某一台 zabbix agent 的模板由原来的 Template OS Windows by Zabbix agent 换成了 Templa…

第一章:项目整体介绍【基于Servlet+JSP的图书管理系统】

一、项目介绍 1.项目说明 本项目是一个完全从0带领大家实现的一个非常基础的WEB项目&#xff0c;非常适合零基础和在校的大学生来动手实现。既能提升技术熟练度了解软件开发的具体过程。同时也能帮助大家搞定毕业设计的需求。之前在B站也分享了一个图书管理系统的视频。但是实…

超简单 display:flex教学

display 弹性盒子解释 Flex是Flexible Box的缩写&#xff0c;意为"弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性。 它的作用&#xff1a; 它能够更加高效方便的控制元素的对齐、排列。 可以自动计算布局内元素的尺寸&#xff0c;无论这个元素的尺寸是固定的还是…

如何用文字生成图片?试试这几个方法吧

在日常生活中&#xff0c;想必很多小伙伴都喜欢绘画&#xff0c;但碍于自己平时需要上班、学习等等&#xff0c;没有时间去进行创作。不过&#xff0c;现在已经有很多ai绘画工具能帮助我们进行创作&#xff0c;而且操作简单&#xff0c;无需经验也可轻松上手&#xff0c;但你知…

三章:局域网架设+文件夹共享+防火墙配置

目录 一、路由器架设局域网 二、配置文件夹共享功能 为什么需要配置文件夹共享功能&#xff1f; 访问共享文件夹 配置取消用户名和密码认证 三、winServer2008防火墙配置 一、路由器架设局域网 1、进入路由器的管理界面 2、网络参数 -> LAN口设置 3、IP地址为路由器的ip…

大数据应用——HBASE实验

任务一&#xff1a;搭建HBase集群 1.1 搭建Zookeeper 1. 官网下载Linux环境的tar包 &#xff08;1&#xff09;官网地址&#xff1a;Apache ZooKeeper &#xff08;2&#xff09;下载Linux环境的tar包 2. 拷贝安装包到Linux系统下并解压到指定目录 [hadoophadoop101 softwar…

佩戴舒适的蓝牙耳机推荐,内行推荐这五大品牌蓝牙耳机

真无线蓝牙耳机怎么选购&#xff1f;对新手来说有点难度&#xff0c;看见很多网友都在讨论这些问题&#xff0c;蓝牙耳机什么品牌好&#xff1f;音质表现好的有哪些&#xff1f;佩戴舒适性好的又有哪些值得入手的&#xff1f;等等大量问题。我从网上整理五款佩戴舒适且音质表现…

linux(线程互斥与同步下)

目录&#xff1a; 1.条件变量概念 2.生产者消费者模型 3.将条件变量生产者消费者blockqueue&#xff08;阻塞队列&#xff09;生产者消费者模型 4.重新复盘生产者消费者模型应用的理解 ------------------------------------------------------------------------------------…

智慧垃圾分类大数据可视化监管系统

前言 随着城市化进程的不断加快和居民生活水平的日益提高&#xff0c;城市生活垃圾产生量亦在与日剧增。 建设背景 随着城镇化进程加速、人民生活水平持续提升,城市生活垃圾产生量也在逐年增长。生活垃圾是“放错地方的资源”,能否处理好这些“放错地方的资源”,关系着城乡人…

HackTheBox - 学院【CPTS】复习4 - Web Attacks

Web Attacks 本模块涵盖三种常见的 Web 漏洞&#xff0c;即 HTTP 动词篡改、IDOR 和 XXE&#xff0c;每个漏洞都可能对公司的系统产生重大影响。我们将介绍如何通过各种方法识别、利用和防止它们中的每一个。 HTTP HEAD/GET/POST/PUT/OPTIONS IDOR寻找 一般能够从前端js找到…