• 生成图片验证码(.NET)


    一、生成随机字符串

     方法一:

            public string CreateRandomCode(int codeCount)
            {
                string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,a,b,c,d,e,f,g,h,i,g,k,l,m,n,o,p,q,r,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,s,t,u,v,w,x,y,z";
                string[] allCharArray = allChar.Split(',');
                string randomCode = "";     //声明随机字符串变量
                int temp = -1;
                Random rand = new Random();     //声明随机数对象
                for (int i = 0; i < codeCount; i++)
                {
                    if (temp != -1)
                    {
                        rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
                    }
                    int t = rand.Next(35);
                    if (temp == t)
                    {
                        return CreateRandomCode(codeCount);
                    }
                    temp = t;
                    randomCode += allCharArray[t];
                }
                return randomCode;
            }

     方法二:

            private static string GetRandomString(int length)
            {
                return Guid.NewGuid().ToString("N").Substring((32 - length), length);
            }

    二、创建验证码图片

     实现方法一:

    public byte[] CreateValidateGraphic(string validateCode)
            {
                //声明用于处理由像素数据定义的图像的对象(宽,高)
                Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 16.0), 27);
    
                Graphics g = Graphics.FromImage(image);
                try
                {
                    Random random = new Random();
    
                    g.Clear(Color.White);       //清空图片背景色
    
                    //画图片的干扰线
                    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);
                        g.DrawLine(new Pen(Color.Silver), x1, x2, y1, y2);
                    }
    
                    Font font = new Font("Arial", 14, (FontStyle.Bold | FontStyle.Italic));     //设置字体样式和大小
                    LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                    g.DrawString(validateCode, font, brush, 3, 2);          //绘制指定的字符串
    
                    //画图片的前景干扰线
                    for (int i = 0; i < 100; i++)
                    {
                        int x = random.Next(image.Width);
                        int y = random.Next(image.Height);
                        image.SetPixel(x, y, Color.FromArgb(random.Next()));
                    }
    
                    g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);        //画图片的边框线
    
                    //保存图片数据
                    MemoryStream stream = new MemoryStream();
                    image.Save(stream, ImageFormat.Jpeg);
    
                    //输出图片流
                    return stream.ToArray();
                }
                finally
                {
                    g.Dispose();
                    image.Dispose();
                }
            }

     实现方法二:

            /// <summary>
            /// 由随机字符串,随即颜色背景,和随机线条产生的Image
            /// </summary>
            /// <returns>Image</returns>
            public static byte[] GetVcodeImg(string text, int width = 200, int height = 45, int fontSize = 20)
            //返回 Image
            {
                int charNum = text.Length;
                //声明一个位图对象
                Bitmap bitMap = null;
                //声明一个绘图画面
                Graphics gph = null;
                //创建内存流
                MemoryStream memStream = new MemoryStream();
                Random random = new Random();
                //由给定的需要生成字符串中字符个数 CharNum, 图片宽度 Width 和高度 Height 确定字号 FontSize,
                //确保不因字号过大而不能全部显示在图片上
                int fontWidth = (int)Math.Round(width / (charNum + 2) / 1.3);
                int fontHeight = (int)Math.Round(height / 1.5);
                //字号取二者中小者,以确保所有字符能够显示,并且字符的下半部分也能显示
                fontSize = fontWidth <= fontHeight ? fontWidth : fontHeight;
                //创建位图对象
                bitMap = new Bitmap(width + fontSize, height);
                //根据上面创建的位图对象创建绘图图面
                gph = Graphics.FromImage(bitMap);
                //设定验证码图片背景色
                gph.Clear(GetControllableColor(200));
                //产生随机干扰线条
                for (int i = 0; i < 10; i++)
                {
                    Pen backPen = new Pen(GetControllableColor(100), 2);
                    //线条起点
                    int x = random.Next(width);
                    int y = random.Next(height);
                    //线条终点
                    int x2 = random.Next(width);
                    int y2 = random.Next(height);
                    //划线
                    gph.DrawLine(backPen, x, y, x2, y2);
                }
                //定义一个含10种字体的数组
                String[] fontFamily =
                {
                    "Arial", "Verdana", "Comic Sans MS", "Impact", "Haettenschweiler",
                    "Lucida Sans Unicode", "Garamond", "Courier New", "Book Antiqua", "Arial Narrow"
                };
    
                SolidBrush sb = new SolidBrush(GetControllableColor(0));
                //通过循环,绘制每个字符,
                for (int i = 0; i < text.Length; i++)
                {
                    Font textFont = new Font(fontFamily[random.Next(10)], fontSize, FontStyle.Bold); //字体随机,字号大小30,加粗
                    //每次循环绘制一个字符,设置字体格式,画笔颜色,字符相对画布的X坐标,字符相对画布的Y坐标
                    int space = (int)Math.Round((double)((width - fontSize * (charNum + 2)) / charNum));
                    //纵坐标
                    int y = (int)Math.Round((double)((height - fontSize) / 3));
                    gph.DrawString(text.Substring(i, 1), textFont, sb, fontSize + i * (fontSize + space), y);
                }
                //扭曲图片
                bitMap = TwistImage(bitMap, true, random.Next(3, 5), random.Next(3));
    
                bitMap.Save(memStream, ImageFormat.Gif);
    
                bitMap.Dispose();
    
                return memStream.ToArray();
            }
    
            /// <summary>
            /// 产生一种 R,G,B 均大于 colorBase 随机颜色,以确保颜色不会过深
            /// </summary>
            /// <returns>背景色</returns>
            private static Color GetControllableColor(int colorBase)
            {
                Color color = Color.Black;
    
                Random random = new Random();
                //确保 R,G,B 均大于 colorBase,这样才能保证背景色较浅
                color = Color.FromArgb(random.Next(56) + colorBase, random.Next(56) + colorBase, random.Next(56) + colorBase);
                return color;
            }
    
            /// <summary>
            /// 扭曲图片
            /// </summary>
            /// <param name="srcBmp"></param>
            /// <param name="bXDir"></param>
            /// <param name="dMultValue"></param>
            /// <param name="dPhase"></param>
            /// <returns></returns>
            private static Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
            {
                int leftMargin = 0;
                int rightMargin = 0;
                int topMargin = 0;
                int bottomMargin = 0;
    
                float PI2 = 6.28318530717959f;
                Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
                double dBaseAxisLen = bXDir ? Convert.ToDouble(destBmp.Height) : Convert.ToDouble(destBmp.Width);
                for (int i = 0; i < destBmp.Width; i++)
                {
                    for (int j = 0; j < destBmp.Height; j++)
                    {
                        double dx = 0;
                        dx = bXDir ? PI2 * Convert.ToDouble(j) / dBaseAxisLen : PI2 * Convert.ToDouble(i) / dBaseAxisLen;
                        dx += dPhase;
                        double dy = Math.Sin(dx);
                        //取得当前点的颜色
                        int nOldX = 0;
                        int nOldY = 0;
                        nOldX = bXDir ? i + Convert.ToInt32(dy * dMultValue) : i;
                        nOldY = bXDir ? j : j + Convert.ToInt32(dy * dMultValue);
                        var color = srcBmp.GetPixel(i, j);
                        if (nOldX >= leftMargin && nOldX < destBmp.Width - rightMargin && nOldY >= bottomMargin &&
                            nOldY < destBmp.Height - topMargin)
                        {
                            destBmp.SetPixel(nOldX, nOldY, color);
                        }
                    }
                }
                return destBmp;
            }
    View Code

    三、将 8位字节数组 转换为 base64字符串 类型的数据

            private String BytesToBase64(Byte[] bytes)
            {
                try
                {
                    return Convert.ToBase64String(bytes);
                }
                catch
                {
                    return null;
                }
            }

    四、接口与调用

      本例是在网站中通过 ashx 文件写的

    调用以上三个方法:

            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                StrHelper sh = new StrHelper(context);    //自己写的类,这里用来返回json数据
    
                string code = CreateRandomCode(4);       //验证码的字符为4个
                string image = BytesToBase64(CreateValidateGraphic(code));    //将图片验证码用base64类型的字符串返回(便于前端显示)
                sh.RebackJson(new { status = 200, code = code, image = image, type = "image/Jpeg" });
            }

     在页面中调用:

    <a >
        <img id="img1" src="" onclick="changeImage()"/>
    </a>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script>
        window.onload = function () {
            changeImage();
        }
        function changeImage() {
            $.ajax({
                url: "http://服务器地址:端口号/SecurityCode.ashx",
                type: "post",
                success: function (data) {
                    data = JSON.parse(data);
    
                    console.log(data);
                    $("#img1").attr("src", 'data:image/png;base64,' + data.image);
                },
                error: function (data) { },
            })
        }
    </script>

     实现方式二 -- 存储到 Redis 缓存中

            /// <summary>
            /// 生成验证码
            /// </summary>
            /// <returns></returns>
            public static async Task<VCode_Return> GetCodeAsync()
            {
                //生成数字并保存,将和图片的base64返回
                var text = GetRandomString(4);
    
                 string vid = ObjectId.GenerateNewId().ToString();
    
                //存储缓存
                await Redis.TopOauth.StringSetAsync($"VCODE:{vid}", text.ToLower(), new TimeSpan(0, 3, 0));
    
                var bytes = GetVcodeImg(text);
                //生成图片
                string imgbase64 = Convert.ToBase64String(bytes);
                //返回验证码
                VCode_Return myReturn = new VCode_Return { vcode_image = imgbase64, vcodeid = vid };
                return myReturn;
            }

    1

  • 相关阅读:
    杭电2042
    杭电2041
    杭电2040
    杭电2046
    SPOJ
    SPOJ
    SPOJ
    HDU
    HDU
    HDU
  • 原文地址:https://www.cnblogs.com/zhangchaoran/p/7683295.html
Copyright © 2020-2023  润新知