C#实现数字验证码

news2024/11/17 15:32:03

开发环境:VS2019,.NET Core 3.1,ASP.NET Core API

1、建立一个验证码控制器

新建两个方法Create和Check,Create用于创建验证码,Check用于验证它是否有效。

声明一个静态类变量存放列表,列表中存放包含令牌和验证码的对象。

        private static List<VCodeModel> _list = new List<VCodeModel>();

        /// <summary>
        /// 返回一个图形验证码和令牌.
        /// </summary>
        /// <returns></returns>
        /// <remarks>这一步需要生成一个数字,并将数字放入图片中,并返回一个令牌,下次验证的时候需要核对令牌和数字是否对应,这些东西保存到类变量中.</remarks>
        [HttpGet]
        public string Create()
        {
            try
            {
                VCodeModel model = new VCodeModel();
                model.id = Guid.NewGuid().ToString();    // 生成令牌
                var vcode = Utils.GetVCode();    // 生成验证码
                model.code = vcode;
                _list.Add(model);    // 记录到缓存中

                // 返回对象
                VCodeController_Create_Receive result = new VCodeController_Create_Receive();
                result.code = "0";
                result.data = new VCodeController_Create_Receive.Data();
                result.data.id = model.id;
                var image = Utils.DrawImage(vcode);
                var base64 = Utils.BitmapToBase64Str(image);
                result.data.img = base64;
                var json = JsonConvert.SerializeObject(result);
                return json;
            }
            catch (Exception ex)
            {
                _logger.LogError(exception: ex, message: ex.Message);
                ReceiveObject result = new ReceiveObject();
                result.code = "999999";
                result.msg = "系统异常";
                var json = JsonConvert.SerializeObject(result);
                return json;
            }
        }

        /// <summary>
        /// 检查验证码是否有效
        /// </summary>
        /// <param name="id">令牌.</param>
        /// <param name="code">验证码.</param>
        /// <returns></returns>
        [HttpGet]
        public string Check(string id, string code)
        {
            try
            {
                var index = _list.FindIndex(m =>
                {
                    if (m.id.Equals(id) && m.code.Equals(code))
                    {
                        return true;
                    }

                    return false;
                });

                ReceiveObject result = new ReceiveObject();
                if (index >= 0)
                {
                    _list.RemoveAt(index);
                    result.code = "0";
                    result.msg = "验证成功";
                    var json = JsonConvert.SerializeObject(result);
                    return json;
                }
                else
                {
                    result.code = "1";
                    result.msg = "验证失败";
                    var json = JsonConvert.SerializeObject(result);
                    return json;
                }
            }
            catch(Exception ex)
            {
                _logger.LogError(exception: ex, message: ex.Message);
                ReceiveObject result = new ReceiveObject();
                result.code = "999999";
                result.msg = "系统异常";
                var json = JsonConvert.SerializeObject(result);
                return json;
            }
        }

2、建立一个验证码模型

验证码模型类包括:令牌和验证码属性。

再创建一个类存放Create方法返回的对象包括:令牌,验证码图片。

    /// <summary>
    /// VCodeController用到的类变量.
    /// </summary>
    public class VCodeModel
    {
        /// <summary>
        /// 令牌.
        /// </summary>
        public string id { get; set; }

        /// <summary>
        ///验证码.
        /// </summary>
        public string code { get; set; }
    }

    /// <summary>
    /// VCodeController控制器中Create方法的返回对象.
    /// </summary>
    public class VCodeController_Create_Receive : ReceiveObject
    {
        public Data data { get; set; }

        public class Data
        {
            /// <summary>
            /// 令牌.
            /// </summary>
            public string id { get; set; }

            /// <summary>
            /// Base64的验证码图片.
            /// </summary>
            public string img { get; set; }
        }
    }

3、建立一个验证码生成器
创建用于生成4位随机数的方法。

创建将随机数绘制成图片的方法。

        static readonly char[] list = new char[10] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };

        /// <summary>
        /// 获取随机验证码.
        /// </summary>
        /// <returns></returns>
        public static string GetVCode()
        {
            Random random = new Random();
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < 4; i++)
            {
                var index = random.Next(0, list.Length);
                builder.Append(list[index]);
            }

            return builder.ToString();
        }

        /// <summary>
        /// 绘制验证码的图片.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static Bitmap DrawImage(string code)
        {
            Color[] list_color =
            {
                Color.FromArgb(240, 230, 140),    // 黄褐色(亮)
                Color.FromArgb(138, 54, 15),    // 黄褐色(暗)
                Color.FromArgb(51, 161, 201),    // 蓝色(亮)
                Color.FromArgb(25, 25, 112),    // 蓝色(暗)
                Color.FromArgb(192, 192, 192),    // 灰白(亮)
                Color.FromArgb(128, 128, 105),    // 灰白(暗)
            };

            Random random = new Random();

            // 创建画板
            Bitmap bitmap = new Bitmap(150, 50);

            // 创建画笔
            Graphics grp = Graphics.FromImage(bitmap);
            grp.Clear(Color.White);    // 设置背景色为白色

            // 绘制噪点
            for (int i = 0; i < random.Next(60, 80); i++)
            {
                int x = random.Next(bitmap.Width);
                int y = random.Next(bitmap.Height);
                grp.DrawLine(new Pen(Color.LightGray, 1), x, y, x + 1, y);
            }

            // 绘制随机的线条
            grp.DrawLine(
                new Pen(list_color[random.Next(list_color.Length)], random.Next(3)),
                new Point(random.Next(bitmap.Width / 2), random.Next(bitmap.Height / 2)),
                new Point(bitmap.Width / 2 + random.Next(bitmap.Width / 2), bitmap.Height / 2 + random.Next(bitmap.Height / 2))
            );

            // 绘制验证码
            for (int i = 0; i < code.Length; i++)
            {
                var item = code[i];
                grp.DrawString(item.ToString(),
                    new Font(FontFamily.GenericSansSerif, 25, FontStyle.Bold),
                    new SolidBrush(list_color[random.Next(list_color.Length)]),
                    x: (150 / 4) * i,
                    y: random.Next(5));
            }

            // 在验证码上绘制噪点
            for (int i = 0; i < random.Next(30, 50); i++)
            {
                int x = random.Next(bitmap.Width);
                int y = random.Next(bitmap.Height);
                grp.DrawLine(new Pen(list_color[random.Next(list_color.Length)], 1), x, y, x + 1, y);
            }

            // 绘制随机的线条
            grp.DrawLine(
                new Pen(list_color[random.Next(list_color.Length)], random.Next(3)),
                new Point(random.Next(bitmap.Width / 2), random.Next(bitmap.Height / 2)),
                new Point(bitmap.Width / 2 + random.Next(bitmap.Width / 2), bitmap.Height / 2 + random.Next(bitmap.Height / 2))
            );

            return bitmap;
        }

        /// <summary>
        /// 将图片对象转成Base64的字符串.
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static string BitmapToBase64Str(Bitmap bitmap)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                bitmap.Save(memoryStream, ImageFormat.Jpeg);
                byte[] bytes = memoryStream.ToArray();
                return Convert.ToBase64String(memoryStream.ToArray());
            }
        }

运行效果:

参考:C# 绘制验证码图片_c#生成验证码图片_耕耘虫的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800229.html

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

相关文章

【论文阅读】定制化diffusion微调: DreamBooth原理

论文&#xff1a;DreamBooth: Fine Tuning Text-to-Image Diffusion Models for Subject-Driven Generation 项目&#xff1a;DreamBooth: Fine Tuning Text-to-Image Diffusion Models for Subject-Driven Generation 代码&#xff1a;Dreambooth-Stable-Diffusion 1. 任务简…

8. Spring Boot 日志文件

目录 1. 日志的作用 2. 如何使用日志 3. 自定义日志打印 3.1 获取日志对象 3.2 设置打印的内容 3.3 常见的日志框架 3.4 日志格式说明 4. 日志级别 4.1 日志级别的作用 4.2 日志级别的分类 4.3 日志级别的使用 4.4 设置日志级别 4.5 分目录设置日志级别 5. 日志…

达梦数据库-下载安装、基本操作及报错处理

下载安装 懒得记官网直接上网搜 产品下载-达梦数据 里面我是按图选择的Dm8 X86 Win64 下载完成后 解压 得到两个文件,打开上面这个ISO文件 打开安装包 setup.exe 这里默认选择中国时间 根据指示一步一步安装即可 选择刚刚安装的DM管理工具即可进入 基本操作 -- 获取所有…

SOLIDWORKS PDM只读文件的处理方法

如果用户检出一个文件&#xff0c;该文件在 SolidWorks 或其他应用程序中仍然以只读形式装入&#xff0c;最常见的原因包括&#xff1a; 1. 核实正在检出的文件尚未在现有 SolidWorks 进程中以只读方式打开。 这是一个常见错误&#xff0c;用户已经在 SolidWorks 打开了装配体…

MySQL界面客户端及高级的复杂查询

十五、MySQL界面客户端 十六、高级的复杂查询 1、查询去重 2、分组查询 gender和name没有同时相同的&#xff0c;相当于没分组 3、别名的使用 4、分组后的筛选 5、排序 6、分页 7、查询的顺序

Vue源码学习 - 异步更新队列 和 nextTick原理

目录 前言一、Vue异步更新队列二、nextTick 用法三、原理分析四、nextTick 源码解析1&#xff09;环境判断2&#xff09;nextTick() 五、补充 前言 在我们使用Vue的过程中&#xff0c;基本大部分的 watcher 更新都需要经过 异步更新 的处理。而 nextTick 则是异步更新的核心。…

【能量管理系统( EMS )】基于粒子群算法对光伏、蓄电池等分布式能源DG进行规模优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于量子同态加密的安全多方凸包协议

摘要安全多方计算几何(SMCG)是安全多方计算的一个分支。该协议是为SMCG中安全的多方凸包计算而设计的。首先&#xff0c;提出了一种基于量子同态加密的安全双方值比较协议。由于量子同态加密的性质&#xff0c;该协议可以很好地保护量子电路执行过程中数据的安全性和各方之间的…

分享一套功能齐全的免费开源MES系统

万界星空科技的开源MES功能&#xff1a; 1、基础数据管理&#xff1a; 2、质量管理&#xff1a; 质检项目维护&#xff0c;根据物料或者型号管理质检项目。检验页面&#xff0c;抽检确认。 3、工艺文件管理 &#xff1a;工艺参数&#xff0c;BOM文件&#xff0c;导入导出 报表&…

【树莓派入门】

一、镜像烧录 烧录器&#xff1a;Raspberry Pi Imager 下载链接&#xff1a;树莓派镜像烧录器下载 创建 ssh 文件 手动创建一个空白记事本.txt文件&#xff0c;命名为ssh&#xff0c;重命名&#xff0c;删掉.txt扩展名。将这个文件放入SD卡的boot盘中 wpa_supplicant.conf …

电流源电路

3.3.3电流源电路 镜像电流源 电路 分析 仿真 比例电流源 电路 分析 仿真 加射极输出器的电流源1 电路 分析 仿真 加射极输出器的电流源2 电路 分析 仿真 威尔逊电流源 电路 分析 仿真

Docker 全栈体系(八)

Docker 体系&#xff08;高级篇&#xff09; 六、Docker轻量级可视化工具Portainer 1. 是什么 Portainer 是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 2. 安装 官网 https://www.portain…

QTday3消息弹框/计时器

闹钟小软件 widget.cpp #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QPushButton> #include <QLabel> #include <QTimer> #include <QTimerEvent> #include <QTime> #include <QMessageB…

版本适配好帮手 Android SDK Upgrade Assistant / Android Studio Giraffe新功能

首先是新版本一顿下载↓&#xff1a; Download Android Studio & App Tools - Android Developers 在Tools中找到Android SDK Upgrade Assistant 可以在此直接查看SDK升级相关信息&#xff0c;不用跑到WEB端去查看了。 例如看一下之前经常要对老项目维护的android 12蓝牙…

umy-ui树形结构表格懒加载用法详解

效果图 在做后台时&#xff0c;使用的iview组件库中的树形表格&#xff0c;但数据量过大时会导致页面卡死&#xff0c;借助umy-ui的虚拟表格完美解决了数据量大卡顿的问题。 先放文档&#xff1a;http://www.umyui.com/umycomponent/u-table-column-api 安装 npm install u…

Ubuntu Server版 之 mysql 系列

Ubuntu 分 桌面版 和 服务版 桌面版 &#xff1a;有额外的简易界面 服务版&#xff1a;是纯黑框的。没有任何UI界面的可言 安装mysql 安装位置 一般按照的位置存放在 /usr/bin 中 sudo apt-get install mysql-server查看mysql的状态 service mysql status mysql 安全设置…

对原型、原型链的理解

在 JavaScript 中是使用构造两数来新建一个对象的&#xff0c;每一个构造函数的内部都有一个 prototype 属性&#xff0c;它的属性值是一个对象&#xff0c;这个对象包含了可以由该构造西数的所有实例共享的属性和方法。当使用构造函数新建一个对象后&#xff0c;在这个对象的内…

js加载和长任务

js加载和长任务 本文将讲解以下浏览器如何加载js&#xff0c;并介绍一些可以提高网页加载速度的方法。 Evaluate Script 如果我们在devtools的performance中分析过网站的加载性能&#xff0c;可能会看到一个很长的任务&#xff0c;叫做Evaluate Script. 在这种情况下&#x…

IDS(Intrusion Detection Systems)

计算机安全的三大中心目标是&#xff1a;保密性(Conf idential ity)、完整性(Integrity)、可用性(Availability)。 身份认证与识别、访问控制机制、加密技术、防火墙技术等技术共同特征就是集中在系统的自身加固和 防护上&#xff0c;属于静态的安全防御技术&#xff0c;缺乏主…

【微服务架构设计】微服务不是魔术:处理超时

微服务很重要。它们可以为我们的架构和团队带来一些相当大的胜利&#xff0c;但微服务也有很多成本。随着微服务、无服务器和其他分布式系统架构在行业中变得更加普遍&#xff0c;我们将它们的问题和解决它们的策略内化是至关重要的。在本文中&#xff0c;我们将研究网络边界可…