驗證碼的種類與實現 C#封裝類 - .NET MVC WEBFORM

驗證碼方式

 

一、隨機字母或者數字,純文本驗證碼

這種很是容易破解 ,市場上有大量的現成接口或者工具,背景越複雜難度越高。程序員

 

二、題庫驗證碼

要破解這種驗證碼,須要人工收集題庫才能夠破解,能夠免疫不是專門針對你一個網站的黑客,因此我偏心這種驗證碼dom

1+1=? •本論壇的域名是? •今天是星期幾? •複雜點的數學運算



可是他究竟是不是就不能破解了呢?

缺點:數量有限。破解方式也很簡單,多刷新幾回,創建題庫和對應的答案,用正則從網頁裏抓取問題,尋找匹配的答案後破解。也有些用隨機生成的數學公式,好比 隨機數 [+-*/]隨機運算符 隨機數=?,小學生水平的程序員也能夠搞定……


題庫越多高全係數越高


 三、干擾型題庫驗證碼

  將文字顯示進行處理起到干擾效果,就算你有正確題庫也不能輕易破解工具

 

 

今天正好身體不舒服請了天假整理了這麼一個能夠實現上面三種驗證碼的類字體

 
效果圖

 

實現步驟

 

一、MVC Action 或者 WebForm的 pageLoad寫如下代碼

 public void ValidateImg()
        {
            VerifyCodeSugar v = new VerifyCodeSugar();

            //是否隨機字體顏色
            v.SetIsRandomColor = true;
            //隨機碼的旋轉角度
            v.SetRandomAngle = 4;
            //文字大小
            v.SetFontSize = 15;
            //背景色
            //v.SetBackgroundColor
            //前景噪點數量
            //v.SetForeNoisePointCount = 3; 
            //v.SetFontColor =Color.Red;
            //...還有更多設置不介紹了

            var questionList = new Dictionary<string, string>()
            {

                {"1+1=?","2"},
                {"喜羊羊主角叫什麼名字?","喜羊羊" },
                {"【我愛你】中間的那個字?","愛" },
            };

            var questionItem = v.GetQuestion();//不賦值爲隨機驗證碼 例如: 1*2=? 這種

            //指定驗證文本
            //v.SetVerifyCodeText

            v.SetVerifyCodeText = questionItem.Key;

            Session["VerifyCode"] = questionItem.Value;

            //輸出圖片
            v.OutputImage(System.Web.HttpContext.Current.Response);

        }

  

 

二、前臺設用action或者pageload頁面地址,js給src更換url添加隨機參數 達到刷新驗證碼的功能網站

 <img src="/File/ValidateImg" />

 

三、完整封裝類ui

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;

namespace Idea.Models
{

    /// <summary>
    /// 驗證碼類
    /// </summary>
    public class VerifyCodeSugar
    {
        private Random objRandom = new Random();

        #region setting 

        /// <summary>
        /// //驗證碼長度
        /// </summary>
        public int SetLength = 4;
        /// <summary>
        /// 驗證碼字符串
        /// </summary>
        public string SetVerifyCodeText { get; set; }
        /// <summary>
        /// 是否加入小寫字母
        /// </summary>
        public bool SetAddLowerLetter = false;
        /// <summary>
        /// 是否加入大寫字母
        /// </summary>
        public bool SetAddUpperLetter = false;
        /// <summary>
        /// 字體大小
        /// </summary>
        public int SetFontSize = 18;
        /// <summary>
        ///  //字體顏色
        /// </summary>
        public Color SetFontColor = Color.Blue;
        /// <summary>
        /// 字體類型
        /// </summary>
        public string SetFontFamily = "Verdana";
        /// <summary>
        /// 背景色
        /// </summary>
        public Color SetBackgroundColor = Color.AliceBlue;
        /// <summary>
        /// 前景噪點數量
        /// </summary>
        public int SetForeNoisePointCount = 2;
        /// <summary>
        /// 隨機碼的旋轉角度
        /// </summary>
        public int SetRandomAngle = 40;

        /// <summary>
        /// 是否隨機字體顏色
        /// </summary>
        public bool SetIsRandomColor = false;
        /// <summary>
        /// 圖片寬度
        /// </summary>
        private int SetWith
        {
            get
            {
                return this.SetVerifyCodeText.Length * SetFontSize;
            }
        }
        /// <summary>
        /// 圖片高度
        /// </summary>
        private int SetHeight
        {
            get
            {
                return Convert.ToInt32((60.0 / 100) * SetFontSize + SetFontSize);
            }
        }
        #endregion

        #region Constructor Method
        public VerifyCodeSugar()
        {
            this.GetVerifyCodeText();
        }
        #endregion

        #region Private Method
        /// <summary>
        /// 獲得驗證碼字符串
        /// </summary>
        private void GetVerifyCodeText()
        {

            //沒有外部輸入驗證碼時隨機生成
            if (String.IsNullOrEmpty(this.SetVerifyCodeText))
            {
                StringBuilder objStringBuilder = new StringBuilder();

                //加入數字1-9
                for (int i = 1; i <= 9; i++)
                {
                    objStringBuilder.Append(i.ToString());
                }

                //加入大寫字母A-Z,不包括O
                if (this.SetAddUpperLetter)
                {
                    char temp = ' ';

                    for (int i = 0; i < 26; i++)
                    {
                        temp = Convert.ToChar(i + 65);

                        //若是生成的字母不是'O'
                        if (!temp.Equals('O'))
                        {
                            objStringBuilder.Append(temp);
                        }
                    }
                }

                //加入小寫字母a-z,不包括o
                if (this.SetAddLowerLetter)
                {
                    char temp = ' ';

                    for (int i = 0; i < 26; i++)
                    {
                        temp = Convert.ToChar(i + 97);

                        //若是生成的字母不是'o'
                        if (!temp.Equals('o'))
                        {
                            objStringBuilder.Append(temp);
                        }
                    }
                }

                //生成驗證碼字符串
                {
                    int index = 0;

                    for (int i = 0; i < SetLength; i++)
                    {
                        index = objRandom.Next(0, objStringBuilder.Length);

                        this.SetVerifyCodeText += objStringBuilder[index];

                        objStringBuilder.Remove(index, 1);
                    }
                }
            }
        }

        /// <summary>
        /// 獲得驗證碼圖片
        /// </summary>
        private Bitmap GetVerifyCodeImage()
        {
            Bitmap result = null;

            //建立繪圖
            result = new Bitmap(SetWith, SetHeight);

            using (Graphics objGraphics = Graphics.FromImage(result))
            {
                objGraphics.SmoothingMode = SmoothingMode.HighQuality;

                //清除整個繪圖面並以指定背景色填充
                objGraphics.Clear(this.SetBackgroundColor);

                //建立畫筆
                using (SolidBrush objSolidBrush = new SolidBrush(this.SetFontColor))
                {
                    this.AddForeNoisePoint(result);

                    this.AddBackgroundNoisePoint(result, objGraphics);

                    //文字居中
                    StringFormat objStringFormat = new StringFormat(StringFormatFlags.NoClip);

                    objStringFormat.Alignment = StringAlignment.Center;
                    objStringFormat.LineAlignment = StringAlignment.Center;

                    //字體樣式
                    Font objFont = new Font(this.SetFontFamily, objRandom.Next(this.SetFontSize - 3, this.SetFontSize), FontStyle.Regular);

                    //驗證碼旋轉,防止機器識別
                    char[] chars = this.SetVerifyCodeText.ToCharArray();

                    for (int i = 0; i < chars.Length; i++)
                    {
                        //轉動的度數
                        float angle = objRandom.Next(-this.SetRandomAngle, this.SetRandomAngle);

                        objGraphics.TranslateTransform(12, 12);
                        objGraphics.RotateTransform(angle);
                        objGraphics.DrawString(chars[i].ToString(), objFont, objSolidBrush, -2, 2, objStringFormat);
                        objGraphics.RotateTransform(-angle);
                        objGraphics.TranslateTransform(2, -12);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 添加前景噪點
        /// </summary>
        /// <param name="objBitmap"></param>
        private void AddForeNoisePoint(Bitmap objBitmap)
        {
            for (int i = 0; i < objBitmap.Width * this.SetForeNoisePointCount; i++)
            {
                objBitmap.SetPixel(objRandom.Next(objBitmap.Width), objRandom.Next(objBitmap.Height), this.SetFontColor);
            }
        }

        /// <summary>
        /// 添加背景噪點
        /// </summary>
        /// <param name="objBitmap"></param>
        /// <param name="objGraphics"></param>
        private void AddBackgroundNoisePoint(Bitmap objBitmap, Graphics objGraphics)
        {
            using (Pen objPen = new Pen(Color.Azure, 0))
            {
                for (int i = 0; i < objBitmap.Width * 2; i++)
                {
                    objGraphics.DrawRectangle(objPen, objRandom.Next(objBitmap.Width), objRandom.Next(objBitmap.Height), 1, 1);
                }
            }

        }

        /// <summary>
        /// 獲取隨機顏色
        /// </summary>
        /// <returns></returns>
        private Color GetRandomColor()
        {
            Random RandomNum_First = new Random((int)DateTime.Now.Ticks);
            // 對於C#的隨機數,沒什麼好說的
            System.Threading.Thread.Sleep(RandomNum_First.Next(50));
            Random RandomNum_Sencond = new Random((int)DateTime.Now.Ticks);
            // 爲了在白色背景上顯示,儘可能生成深色
            int int_Red = RandomNum_First.Next(256);
            int int_Green = RandomNum_Sencond.Next(256);
            int int_Blue = (int_Red + int_Green > 400) ? 0 : 400 - int_Red - int_Green;
            int_Blue = (int_Blue > 255) ? 255 : int_Blue;
            return Color.FromArgb(int_Red, int_Green, int_Blue);
        }
        #endregion

        #region Public Method
        /// <summary>
        /// 輸出驗證碼圖片
        /// </summary>
        /// <param name="objHttpResponse">Http響應實例</param>
        /// <returns>輸出是否成功</returns>
        public bool OutputImage(HttpResponse objHttpResponse)
        {
            bool result = false;
            if (this.SetIsRandomColor)
            {
                this.SetFontColor = GetRandomColor(); ;
            }

            using (Bitmap objBitmap = this.GetVerifyCodeImage())
            {
                if (objBitmap != null)
                {
                    using (MemoryStream objMS = new MemoryStream())
                    {
                        objBitmap.Save(objMS, ImageFormat.Jpeg);

                        HttpContext.Current.Response.ClearContent();
                        HttpContext.Current.Response.ContentType = "image/Jpeg";
                        HttpContext.Current.Response.BinaryWrite(objMS.ToArray());
                        HttpContext.Current.Response.Flush();
                        HttpContext.Current.Response.End();

                        result = true;
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 獲取問題
        /// </summary>
        /// <param name="questionList">默認數字加減驗證</param>
        /// <returns></returns>
        public KeyValuePair<string, string> GetQuestion(Dictionary<string, string> questionList = null)
        {
            if (questionList == null)
            {
                questionList = new Dictionary<string, string>();
                var operArray = new string[] { "+", "*", "num" };
                var left = objRandom.Next(0, 10);
                var right = objRandom.Next(0, 10);
                var oper = operArray[objRandom.Next(0, operArray.Length)];
                if (oper == "+")
                {
                    string key = string.Format("{0}+{1}=?", left, right);
                    string val = (left + right).ToString();
                    questionList.Add(key, val);
                }
                else if (oper == "*")
                {
                    string key = string.Format("{0}×{1}=?", left, right);
                    string val = (left * right).ToString();
                    questionList.Add(key, val);
                }
                else
                {
                    var num = objRandom.Next(1000, 9999); ;
                    questionList.Add(num.ToString(), num.ToString());
                }
            }
            return questionList.ToList()[objRandom.Next(0, questionList.Count)];
        }
        #endregion
    }

}

  

爲嘛就一個類寫這麼多,沒排版博客園不給推薦到首頁。。

相關文章
相關標籤/搜索