C# 生成验证码

2021年7月21日 1793点热度 0人点赞 0条评论
内容纲要

在 ASP.NET Core 中生成验证码的方法以及代码:

引入 ZKWeb.System.Drawing ,其代码示例如下:

    /// <summary>
    /// 验证码服务
    /// </summary>
    public class VerificationCode
    {
        // 验证码有效期(秒)
        private const int ValiditySecond = 60;

        // 宽、高,字体大小
        private const int CodeWidth = 74;
        private const int CodeHeight = 36;
        private const int FontSize = 16;

        // 验证码长度
        private const int CodeLength = 4;
        // 躁线、躁点 个数
        private const int ManicLine = 5;
        private const int ManicPoint = 100;

        // 种子长度,即数组的索引范围
        private static readonly int SeedOriginLength = SeedOrigin.Length;

        // 种子
        private static readonly char[] SeedOrigin = new char[]
        {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b','c','d','e','f','g','h','i','j','k','l','m',
                'n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K',
                'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        };

        // 颜色列表
        private static readonly Color[] Colors = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.DarkBlue };
        // 字体列表
        private static readonly string[] fonts = { "Times New Roman", "Verdana", "Arial", "Gungsuh" };

        // 验证码缓存
        private static readonly ConcurrentDictionary<ulong, CodeCheck> CodeCache = new ConcurrentDictionary<ulong, CodeCheck>();

        /// <summary>
        /// 生成验证码
        /// </summary>
        /// <returns></returns>
        private static string CreateCode(int maxLength)
        {
            char[] code = new char[CodeLength];

            Random random = new Random();

            for (int i = 0; i < CodeLength; i++)
            {
                code[i] = SeedOrigin[random.Next(0, maxLength)];
            }
            return Convert.ToString(code);
        }

        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <returns></returns>
        public (string CodeId, string Code, byte[] ImageBytes) GetCode()
        {
            string code = CreateCode(SeedOriginLength);
            ulong codeId = CommonHelper.CreateId();

            Random random = new Random();

            // 创建画布
            Bitmap bitmap = new Bitmap(CodeWidth, CodeHeight);
            Graphics graphics = Graphics.FromImage(bitmap);
            graphics.Clear(Color.White);

            // 画躁线
            for (int i = 0; i < ManicLine; i++)
            {
                int x1 = random.Next(CodeWidth);
                int y1 = random.Next(CodeHeight);
                int x2 = random.Next(CodeWidth);
                int y2 = random.Next(CodeHeight);
                Color color = Colors[random.Next(Colors.Length)];
                Pen pen = new Pen(color);
                graphics.DrawLine(pen, x1, y1, x2, y2);
            }

            //  画噪点
            for (int i = 0; i < ManicPoint; i++)
            {
                int x = random.Next(CodeWidth);
                int y = random.Next(CodeHeight);
                Color color = Colors[random.Next(Colors.Length)];
                bitmap.SetPixel(x, y, color);
            }

            //画验证码
            for (int i = 0; i < CodeLength; i++)
            {
                string fontStr = fonts[random.Next(fonts.Length)];
                Font font = new Font(fontStr, FontSize);
                Color color = Colors[random.Next(Colors.Length)];
                graphics.DrawString(code[i].ToString(), font, new SolidBrush(color), (float)i * 15 + 2, (float)0);
            }

            try
            {
                MemoryStream stream = new MemoryStream();
                bitmap.Save(stream, ImageFormat.Jpeg);

                CodeCache.TryAdd(codeId, new CodeCheck
                {
                    Id = codeId,
                    DateTime = DateTime.Now,
                    Conent = code
                });
                return (codeId.ToString(), code, stream.ToArray());
            }
            finally
            {
                graphics.Dispose();
                bitmap.Dispose();
            }
        }

        /// <summary>
        /// 检查用户输入的验证码是否正确
        /// </summary>
        /// <param name="codeId"></param>
        /// <param name="codeText"></param>
        /// <returns></returns>
        public bool Check(string codeId, string codeText)
        {
            if (!ulong.TryParse(codeId, out var id) || string.IsNullOrWhiteSpace(codeText))
                return false;
            // 有效期
            if (!CodeCache.TryGetValue(id, out var value) ||
                (DateTime.Now - value.DateTime).TotalSeconds > ValiditySecond)
                return false;
            // 检查验证码是否正确,忽略大小写
            if (!value.Conent.Equals(codeText, StringComparison.OrdinalIgnoreCase))
                return false;

            return true;
        }

        private class CodeCheck
        {
            /// <summary>
            /// 验证码Id
            /// </summary>
            public ulong Id { get; set; }

            /// <summary>
            /// 验证码生成时间
            /// </summary>
            public DateTime DateTime { get; set; }

            /// <summary>
            /// 验证码 Id
            /// </summary>
            public string Conent { get; set; }
        }

    }

痴者工良

高级程序员劝退师

文章评论