.NET 6.0 + 在Linux的Docker容器中 不安装任何依赖生成图形验证码教程

.NET 6.0 + 在Linux的Docker容器中 不安装任何依赖生成图形验证码教程

猿掌柜
2025-12-22 / 0 评论 / 1 阅读 / 正在检测是否收录...

推荐使用SkiaSharp

首先,安装SkiaSharp
编写好图形生成代码。
在windows 上简易代码
using SkiaSharp;
using System.Drawing;
using System.Drawing.Text;

namespace VertifyCode
{
    public class VerifyCodeHelper
    {
        private static readonly char[] Chars = { '0','1','2','3','4','5','6','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' };
        //private static readonly int Width = 90;
        //private static readonly int Height = 35;

        private static string GenCode(int num)
        {
            var code = string.Empty;
            var r = new Random();

            for (int i = 0; i < num; i++)
            {
                code += Chars[r.Next(Chars.Length)].ToString();
            }

            return code;
        }
        /// <summary>
        /// 获取图像数字验证码
        /// </summary>
        /// <returns></returns>
        public static (string code, byte[] bytes) GetVerifyCode()
        {
            var code = GenCode(4);
            int width = 128;
            int height = 45;

            Random random = new();

            //创建bitmap位图
            using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
            //创建画笔
            using SKCanvas canvas = new(image);
            //填充背景颜色为白色
            canvas.DrawColor(SKColors.White);

            //画图片的背景噪音线
            for (int i = 0; i < (width * height * 0.015); i++)
            {
                using SKPaint drawStyle = new();
                drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));

                canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
            }//将文字写到画布上
            using (SKPaint drawStyle = new())
            {
                drawStyle.Color = SKColors.Red;
                drawStyle.TextSize = height;
                drawStyle.StrokeWidth = 1;

                float emHeight = height - (float)height * (float)0.14;
                float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13);
                canvas.DrawText(code, emWidth, emHeight, drawStyle);
            }

            //画图片的前景噪音点
            for (int i = 0; i < (width * height * 0.15); i++)
            {
                image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
            }

            using var img = SKImage.FromBitmap(image);
            using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
            return (code, p.ToArray());
        }
    }
}

mjgfr3h0.png

以上代码docker 不可用,如果需要在linux 上课用,还需要下载SkiaSharp.linux,【SkiaSharp.NativeAssets.Linux.NoDependencies】本篇着重讲在docker 环境下的使用,兼容非docker 容器

在docker 下使用的话需要使用外部字体

[HttpGet]
public FileContentResult Get()
{
    string code;
    var img = Create(out code);
    // Console.WriteLine(code);
    HttpContext.Session.SetString("code", code);
    //GC.Collect();
    return File(img.ToArray(), "image/png");
}
private static string RndNum(int VcodeNum)
{
    //验证码可以显示的字符集合  
    string Vchar = "1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,m,n,p" +
        ",q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q" +
        ",R,S,T,U,V,W,X,Y,Z";
    string[] VcArray = Vchar.Split(new Char[] { ',' });//拆分成数组   
    string code = "";//产生的随机数  
    int temp = -1;//记录上次随机数值,尽量避避免生产几个一样的随机数  

    Random rand = new Random();
    //采用一个简单的算法以保证生成随机数的不同  
    for (int i = 1; i < VcodeNum + 1; i++)
    {
        if (temp != -1)
        {
            rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));//初始化随机类  
        }
        int t = rand.Next(58);//获取随机数  
        if (temp != -1 && temp == t)
        {
            return RndNum(VcodeNum);//如果获取的随机数重复,则递归调用  
        }
        temp = t;//把本次产生的随机数记录起来  
        code += VcArray[t];//随机数的位数加一  
    }
    return code;
}

public static MemoryStream Create(out string code, int numbers = 4)
{
    code = RndNum(numbers);
    MemoryStream ms = new MemoryStream();
    Random random = new Random();
    int width = 72;
    int height = 32;
    var bitmap = new SKBitmap(width, height);
    using (var canvas = new SKCanvas(bitmap))
    {
        canvas.Clear(SKColors.White);

        using (var paint = new SKPaint())
        {
            // 绘制干扰线
            paint.Color = SKColors.LightGray;
            paint.StrokeWidth = 2;
           
            for (int i = 0; i < 5; i++)
            {
                int x1 = random.Next(width);
                int y1 = random.Next(height);
                int x2 = random.Next(width);
                int y2 = random.Next(height);
                canvas.DrawLine(x1, y1, x2, y2, paint);
            }
            // 在随机位置画背景点
            for (int i = 0; i < 100; i++)
            {
                int x = random.Next(width);
                int y = random.Next(height);
                canvas.DrawCircle(x, y, 1, paint);
            }
            SKFont sKFont = new SKFont();
            // 绘制文字
            sKFont.Size = 21;
            paint.IsAntialias = true;
            //sKFont.Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);
            sKFont.Typeface = SKTypeface.FromFile("msyh.ttc");
            float textWidth = sKFont.MeasureText(code,paint);
            SKColor[] fcolor = { SKColors.Black, SKColors.Red, SKColors.DarkBlue, SKColors.Green, SKColors.Orange, SKColors.Brown, SKColors.DarkCyan, SKColors.Purple,SKColors.DeepPink };
            for (int i = 0; i < code.Length; i++)
            {
                int top = random.Next(5, 15);
                int cindex = random.Next(7);
                paint.Color = fcolor[cindex];
                canvas.DrawText(code.Substring(i, 1), 5 + (i * 16), height / 2 + top, sKFont, paint);

            }
        }
    }
    using var image = SKImage.FromBitmap(bitmap);
    using var data = image.Encode(SKEncodedImageFormat.Png, 100);
    //using var stream = new MemoryStream();
    data.SaveTo(ms);
    //bitmap.Save(ms,SerializerCompression.GZip);
    return ms;

}

需要先把字体放在资源目录,记得字体文件要改为始终复制,本篇用到的是微软雅黑

然后打包到linux 放进docker即可成功显示

1

评论 (0)

取消