在Aspnetcore网站中使用图片验证码(一)

admin 449

当从.net framework迁移到.net core 2.0后,原来的图片验证码不能用了,因为.net core里面没有System.Drawing里的各种图像操作(有一个System.Drawing类型定义库),System.Drawing用到了Win平台下的GDI+.

那怎么办呢,没办法,自己选的Core,含着泪也要写完啊。

在Nuget里找找吧,发现没什么能用的第三方库,好多名字起的很好,一安装就是空架子的。最后只能Search english了。

最终用bing搜索到一个ImageSharp项目,原来nuget里面没有是因为都还不是正式版,虽然版本出了好多。

安装包吧:

ImageSharp - 基础库
ImageSharp.Drawing - 图形处理的各种Drawing扩展方法
SixLabors.Shapes.Text - 这个里面依赖了shapes、fonts等(上面ImageSharp.Drawing有依赖这个,但是VS认不出类型来,单独装了)

安装好以后就可以大展身手了,先画个背景吧.... 不对,验证字符都还没有呢。

还是先生成个随机字符串吧,就直接来个最简单的,直接随5位数,也算万元户了

public string CreateValidateCode()
{
    Random rand = new Random();
    retrung rand.Next(10000,99999).ToString();
}

有了验证字符了,就开始画画了:

public byte[] CreateValidateGraphic(string validateCode)
        {
            byte[] result;
            using (Image<Rgba32> image = new Image<Rgba32>((int)Math.Ceiling(validateCode.Length * 12.0), 22)) //这个意思是按12的fontsize建一个对应长度和高为22的Image
            {
                image.BackgroundColor<Rgba32>(Rgba32.White);//先把背景涂白
                Random random = new Random();
                for (int i = 0; i < 25; i++)
                {
                    int x1 = random.Next(image.Width);
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);
                    var points = new PointF[] { new PointF(x1, y1), new PointF(x2, y2) };
                    image.DrawLines(Brushes.Percent10(new Rgba32((byte)random.Next(1,255), (byte)random.Next(1, 255), (byte)random.Next(1, 255))), 5, points);
                }//上面这一大串是画点,别看是DrawLines,但画刷是点的  所以是画了很多点
               var collection = new FontCollection();
                var fo = SixLabors.Fonts.SystemFonts.Find("Arial"); //collection.Install(Path.Combine(_hostingEnvironment.WebRootPath,"fonts\\arial.ttf")); //读取字体,注释这一句是因为有个版本的读系统字体报Stream错,就把字体COPY到项目中手动加载 ,但后来换个版本它又好了
                var font = new Font(fo, 12, FontStyle.Italic);
                var size = TextMeasurer.Measure(validateCode,new RendererOptions(font));
                PointF center = new PointF(image.Width / 2, image.Height / 2);
                float scalingFactor = Math.Min(image.Width / size.Width, image.Height / size.Height);
                Font scaledFont = new Font(font, scalingFactor * font.Size);//上面这些是缩放字体的
                image.DrawText<Rgba32>(validateCode,scaledFont ,Rgba32.Blue, center, new TextGraphicsOptions(true) {  HorizontalAlignment= HorizontalAlignment.Center, VerticalAlignment= VerticalAlignment.Center});
                PointF[] ps = new PointF[] {new PointF(random.Next(image.Width),random.Next(image.Height)), new PointF(random.Next(image.Width), random.Next(image.Height)), new PointF(random.Next(image.Width), random.Next(image.Height)), new PointF(random.Next(image.Width), random.Next(image.Height)) };
                image.DrawPolygon(Rgba32.Blue,1, ps);//估计没几个看注释的,不写了
                var rectPoints = new PointF[] { new PointF(0, 0), new PointF(image.Width - 1, 0), new PointF(image.Width-1,image.Height-1), new PointF(0,image.Height-1) };
                image.DrawPolygon(Rgba32.Silver,1,rectPoints);//这个只是画个边框
                using (MemoryStream stream = new MemoryStream()) {
                    image.SaveAsJpeg(stream);//把画的鸟屎玩意转成Jpeg格式的
                    result = stream.ToArray();//这个转换是因为这个方法没写在Web里 不然可以直接输出来
                        }
            }
            return result;
        }

写好以后,就可以调用了

新建一个CaptchaController,写个Action

public FileStreamResult GetDefaultCaptchaCode()
        {
            DefaultCaptcha _defaultCaptcha = new ImageHelpers.DefaultCaptcha();
            string code = _defaultCaptcha.CreateValidateCode(5);
            //HttpContext.Session.Set(CaptchaSettingNames.SessionName,System.Text.Encoding.UTF8.GetBytes( code));
            HttpContext.Session.Set("goodname",System.Text.Encoding.UTF8.GetBytes(code));
            byte[] bytes = _defaultCaptcha.CreateValidateGraphic(code);
            return new FileStreamResult(new MemoryStream(bytes), "image/jpeg");
        }

启动,输入 http://xxxxxx//Captcha/GetDefaultCaptchaCode  验证码图片就出来了