schangxiang@126.com
2024-04-23 f47411fb53aeee0c7bd514cbc841f9030349f448
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using Admin.NET.Core;
using Furion.DependencyInjection;
using Microsoft.Extensions.Caching.Memory;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using Yitter.IdGenerator;
 
namespace Admin.NET.Application
{
    /// <summary>
    /// 常规验证码
    /// </summary>
    public class GeneralCaptcha : IGeneralCaptcha, ITransient
    {
        private readonly IMemoryCache _memoryCache;
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="memoryCache"></param>
        public GeneralCaptcha(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }
 
        /// <summary>
        /// 生成验证码图片
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public ClickWordCaptchaResult CreateCaptchaImage(int length = 4)
        {
            var rtnResult = new ClickWordCaptchaResult();
 
            var code = GenerateRandom(length); // 随机字符串集合
            rtnResult.RepData.OriginalImageBase64 = Convert.ToBase64String(Draw(code)); //"data:image/jpg;base64," +
            rtnResult.RepData.Token = YitIdHelper.NextId().ToString();
 
            // 缓存验证码正确位置集合
            var cacheOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(30));
            _memoryCache.Set(CommonConst.CACHE_KEY_CODE + rtnResult.RepData.Token, code, cacheOptions);
 
            rtnResult.RepData.Point = null; // 清空位置信息
            return rtnResult;
        }
 
        private static byte[] Draw(string code)
        {
            int codeW = 110;
            int codeH = 36;
            int fontSize = 22;
 
            // 颜色列表,用于验证码、噪线、噪点
            Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
            // 字体列表,用于验证码
            string[] fonts = new[] { "Times New Roman", "Verdana", "Arial", "Gungsuh", "Impact" };
 
            using (var bmp = new Bitmap(codeW, codeH))
            using (var g = Graphics.FromImage(bmp))
            using (var ms = new MemoryStream())
            {
                g.Clear(Color.White);
                var rnd = new Random();
                // 画噪线
                for (int i = 0; i < 1; i++)
                {
                    int x1 = rnd.Next(codeW);
                    int y1 = rnd.Next(codeH);
                    int x2 = rnd.Next(codeW);
                    int y2 = rnd.Next(codeH);
                    var clr = color[rnd.Next(color.Length)];
                    g.DrawLine(new Pen(clr), x1, y1, x2, y2);
                }
 
                // 画验证码字符串
                string fnt;
                Font ft;
                for (int i = 0; i < code.Length; i++)
                {
                    fnt = fonts[rnd.Next(fonts.Length)];
                    ft = new Font(fnt, fontSize);
                    var clr = color[rnd.Next(color.Length)];
                    g.DrawString(code[i].ToString(), ft, new SolidBrush(clr), (float)i * 24 + 2, (float)0);
                }
 
                // 将验证码图片写入内存流
                bmp.Save(ms, ImageFormat.Png);
                return ms.ToArray();
            }
        }
 
        private static string GenerateRandom(int length)
        {
            var chars = new StringBuilder();
            // 验证码的字符集,去掉了一些容易混淆的字符
            char[] character = { '2', '3', '4', '5', '6', '8', '9', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
            Random rnd = new();
            // 生成验证码字符串
            for (int i = 0; i < length; i++)
            {
                chars.Append(character[rnd.Next(character.Length)]);
            }
            return chars.ToString();
        }
 
        /// <summary>
        /// 验证码验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ClickWordCaptchaResult CheckCode(GeneralCaptchaInput input)
        {
            var res = new ClickWordCaptchaResult();
 
            var code = _memoryCache.Get(CommonConst.CACHE_KEY_CODE + input.Token);
            if (code == null)
            {
                res.RepCode = "6110";
                res.RepMsg = "验证码已失效,请重新获取";
                return res;
            }
            if (string.Compare(input.CaptchaCode, (string)code, true) != 0)
            {
                res.RepCode = "6112";
                res.RepMsg = "验证码错误";
                return res;
            }
 
            _memoryCache.Remove(CommonConst.CACHE_KEY_CODE + input.Token);
            res.RepCode = "0000";
            res.RepMsg = "验证成功";
            return res;
        }
    }
}