C# 生成公式验证码

@zgcwkj  2022年12月15日

分类:

代码 其它 

C# 使用 SkiaSharp 实现验证码

代码

/// <summary>
/// 验证码 SkiaSharp 库(不用考虑太多跨平台问题)
///
/// <para>添加包(选择对应平台安装)</para>
/// <para>dotnet add package SkiaSharp</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.Linux</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.macOS</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.Win32</para>
/// </summary>
public class CaptchaCodeSK
{
    /// <summary>
    /// Tuple 的第一个值是表达式
    /// Tuple 的第二个值是表达式结果
    /// </summary>
    /// <returns></returns>
    public static Tuple<string, int> GetCaptchaCode()
    {
        var random = new Random();
        //数据
        var value = 0;
        var first = random.Next(10, 100);//10-99
        var second = random.Next(10, 100);//10-99
        //计算方式
        var operators = new char[] { '+', '-', '×', '÷' };
        var operatorChar = operators[random.Next(0, 2 /** operators.Length **/)];
        switch (operatorChar)
        {
            case '+':
                value = first + second;
                break;
            case '-':
                // 第1个数要大于第二个数
                if (first < second)
                {
                    var temp = first;
                    first = second;
                    second = temp;
                }
                value = first - second;
                break;
            case '×':
                value = first * second;
                break;
            case '÷':
                //被除数不能为零
                if (second == 0)
                {
                    second = 1;
                }
                value = first / second;
                break;
        }
        //公式
        var randomCode = string.Format("{0}{1}{2}=?", first, operatorChar, second);
        //结果
        return new Tuple<string, int>(randomCode, value);
    }

    /// <summary>
    /// 生成验证码图片
    /// </summary>
    /// <param name="randomCode"></param>
    /// <returns></returns>
    public static byte[] CreateCaptchaImage(string randomCode)
    {
        var random = new Random();
        //验证码颜色集合
        var colors = new[] { SKColors.Black, SKColors.Red, SKColors.DarkBlue, SKColors.Green, SKColors.Orange, SKColors.Brown, SKColors.DarkCyan, SKColors.Purple };
        //验证码字体集合
        var fonts = new[] { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
        //相当于js的 canvas.getContext('2d')
        using var image2d = new SKBitmap(100, 30, SKColorType.Bgra8888, SKAlphaType.Premul);
        //相当于前端的canvas
        using var canvas = new SKCanvas(image2d);
        //填充白色背景
        canvas.DrawColor(SKColors.AntiqueWhite);
        //样式 跟xaml差不多
        using var drawStyle = new SKPaint();
        //生成干扰点
        for (int i = 0; i < 50; i++)
        {
            drawStyle.Color = colors[random.Next(colors.Length)];
            drawStyle.StrokeWidth = 1;
            var x1 = random.Next(0, randomCode.Length * 15);
            var y1 = random.Next(0, 60);
            var x2 = x1 + 1;
            var y2 = y1;
            canvas.DrawLine(x1, y1, x2, y2, drawStyle);
        }
        //填充验证码到图片
        for (int i = 0; i < randomCode.Length; i++)
        {
            var fontData = randomCode[i].ToString();
            var fontSize = random.Next(26, 31);
            var fontType = fonts[random.Next(0, fonts.Length - 1)];
            //样式
            drawStyle.IsAntialias = true;
            drawStyle.TextSize = fontSize;
            drawStyle.Typeface = SKTypeface.FromFamilyName(fontType, SKFontStyleWeight.SemiBold, SKFontStyleWidth.ExtraCondensed, SKFontStyleSlant.Upright);
            drawStyle.Color = colors[random.Next(0, colors.Length - 1)];
            //写字
            var x1 = i * 14;
            var y1 = 28;
            canvas.DrawText(fontData, x1, y1, drawStyle);
        }
        //生成干扰线
        for (int i = 0; i < 5; i++)
        {
            drawStyle.Color = colors[random.Next(colors.Length)];
            drawStyle.StrokeWidth = 1;
            var x1 = random.Next(0, randomCode.Length * 15);
            var y1 = random.Next(0, 60);
            var x2 = random.Next(0, randomCode.Length * 16);
            var y2 = random.Next(0, 30);
            canvas.DrawLine(x1, y1, x2, y2, drawStyle);
        }
        //创建对象信息
        using var img = SKImage.FromBitmap(image2d);
        using var p = img.Encode(SKEncodedImageFormat.Png, 100);
        using var ms = new MemoryStream();
        //保存到流
        p.SaveTo(ms);
        var bytes = ms.GetBuffer();
        return bytes;
    }

    /// <summary>
    /// Tuple 的第一个值是表达式结果
    /// Tuple 的第二个值是表达式图片
    /// </summary>
    /// <returns></returns>
    public static Tuple<string, byte[]> GetImgData()
    {
        var tuple = GetCaptchaCode();
        var code = tuple.Item2.ToString();
        var img = CreateCaptchaImage(tuple.Item1);
        return new Tuple<string, byte[]>(code, img);
    }
}

使用方法

var tuple = CaptchaCodeSK.GetImgData();
SessionHelper.Set("ValidateCode", tuple.Item1);
return File(tuple.Item2, "image/jpg");


评论已关闭

Top