asp.net web api實現圖片點擊式圖片驗證碼

来源:http://www.cnblogs.com/liemei/archive/2017/06/21/7060831.html
-Advertisement-
Play Games

現在驗證碼的形式越來越豐富,今天要實現的是在點擊圖片中的文字來進行校驗的驗證碼,如圖 這種驗證碼驗證是驗證滑鼠是否選中了圖片中文字的位置,以及選擇的順序,產生驗證碼的時候可以提供一組底圖,然後隨機獲取一張圖片,隨機選取幾個字,然後把文字的順序打亂,分別隨機放到圖片的一個位置上,然後記錄文字的位置和順 ...


現在驗證碼的形式越來越豐富,今天要實現的是在點擊圖片中的文字來進行校驗的驗證碼,如圖

這種驗證碼驗證是驗證滑鼠是否選中了圖片中文字的位置,以及選擇的順序,產生驗證碼的時候可以提供一組底圖,然後隨機獲取一張圖片,隨機選取幾個字,然後把文字的順序打亂,分別隨機放到圖片的一個位置上,然後記錄文字的位置和順序,驗證的時候驗證一下文字的位置和順序即可

驗證碼圖片的類

    /// <summary>
    /// 二維碼圖片
    /// </summary>
    public class VerCodePic
    {
        /// <summary>
        /// 圖片鏈接
        /// </summary>
        public string PicURL { get; set; }
        /// <summary>
        /// 第一個字位置
        /// </summary>
        public FontPoint Font1 { get; set; }
        /// <summary>
        /// 第二個字位置
        /// </summary>
        public FontPoint Font2 { get; set; }
        /// <summary>
        /// 第三個字位置
        /// </summary>
        public FontPoint Font3 { get; set; }
        /// <summary>
        /// 第四個字位置
        /// </summary>
        public FontPoint Font4 { get; set; }
    }
    /// <summary>
    /// 文字位置
    /// </summary>
    public class FontPoint
    {
        public int X { get; set; }
        public int Y { get; set; }
    }

生成驗證碼圖片驗證碼的方法,在這個方法中指定了生成的驗證碼圖片中字體大小為20個像素,因為驗證碼底圖的大小是固定的,所以就把驗證碼底圖按照字體的大小分成了若幹個網格位置,指定一個文字在圖片中的位置時只需要隨機獲取其中一個網格即可,如果這個網格中沒有指定過文字,那就把文字放到這個網格中。

提前設定網格的方法

  private static ArrayList _FontPoint;
        public static ArrayList FontPoint
        {
            get
            {
                if (_FontPoint==null)
                {
                    _FontPoint = new ArrayList();

                    for (int x=0;x<10;x++)
                    {
                        for (int y=0;y<5;y++)
                        {
                            _FontPoint.Add(new Models.FontPoint() { X = x * 28, Y = y * 20 });
                        }
                    }
                }
                return _FontPoint;
            }
        }

我選定的驗證碼底圖為280*100的,所以按照上邊的方法將圖片分成了若幹個網格,在下邊設定一個文字位置的時候隨機選取其中一個位置,而且給每個字都設定了不一樣的顏色

 /// <summary>
        /// 根據文字和圖片獲取驗證碼圖片
        /// </summary>
        /// <param name="content"></param>
        /// <param name="picFileName"></param>
        /// <returns></returns>
        public static VerCodePic GetVerCodePic(string content,string picFileName,int fontSize=20)
        {
            ClassLoger.Info("FileHelper.GetVerCodePic","開始生成二維碼");
            Bitmap bmp = new Bitmap(picFileName);
            List<int> hlist = new List<int>();
            VerCodePic codepic = new VerCodePic();
            int i = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1);
            codepic.Font1 = SystemSet.FontPoint[i] as FontPoint;
            hlist.Add(i);

            A: int i2 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1);
            if (hlist.Contains(i2))
                goto A;
            codepic.Font2 = SystemSet.FontPoint[i2] as FontPoint;
            hlist.Add(i2);

            B: int i3 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1);
            if (hlist.Contains(i3))
                goto B;
            hlist.Add(i3);
            codepic.Font3 = SystemSet.FontPoint[i3] as FontPoint;

            C: int i4 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1);
            if (hlist.Contains(i4))
                goto C;
            hlist.Add(i4);
            codepic.Font4 = SystemSet.FontPoint[i4] as FontPoint;string fileName = (content + "-" + picFileName+"-"+i+"|"+i2+"|"+i3+"|"+i4).MD5()+Path.GetExtension(picFileName);
            string dir = Path.Combine(SystemSet.ResourcesPath, SystemSet.VerCodePicPath);
            string filePath = Path.Combine(dir, fileName);
            if (File.Exists(filePath))
            {
                codepic.PicURL = string.Format("{0}/{1}/{2}", SystemSet.WebResourcesSite, SystemSet.VerCodePicPath, fileName);
                return codepic;
            }
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            
            Graphics g = Graphics.FromImage(bmp);
            Font font = new Font("微軟雅黑", fontSize, GraphicsUnit.Pixel);
            SolidBrush sbrush = new SolidBrush(Color.Black);
            SolidBrush sbrush1 = new SolidBrush(Color.Peru);
            SolidBrush sbrush2 = new SolidBrush(Color.YellowGreen);
            SolidBrush sbrush3 = new SolidBrush(Color.SkyBlue);
            List<char> fontlist = content.ToList();
            ClassLoger.Info("FileHelper.GetVerCodePic", fontlist.Count.ToString());
            g.DrawString(fontlist[0].TryToString(), font, sbrush, new PointF(codepic.Font1.X, codepic.Font1.Y));
            g.DrawString(fontlist[1].TryToString(), font, sbrush1, new PointF(codepic.Font2.X, codepic.Font2.Y));
            g.DrawString(fontlist[2].TryToString(), font, sbrush2, new PointF(codepic.Font3.X, codepic.Font3.Y));
            g.DrawString(fontlist[3].TryToString(), font, sbrush3, new PointF(codepic.Font4.X, codepic.Font4.Y));

            bmp.Save(filePath, ImageFormat.Jpeg);
            codepic.PicURL = string.Format("{0}/{1}/{2}",SystemSet.WebResourcesSite, SystemSet.VerCodePicPath, fileName);
            return codepic;
        }

獲取圖片驗證碼的api介面,在這個介面中從成語庫中隨機選取了一個成語,然後隨機選取了一個圖片,然後調用生成圖片驗證碼的方法,生成了圖片驗證碼,並且把驗證碼對應的信息緩存在redis中,設定緩存時間,將redis的key作為一個臨時令牌隨同驗證碼返回

 /// <summary>
        /// 獲取驗證碼,有效時間10分鐘
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("vercode")]
        public JsonResult<VerCodePicViewModel> VerCodePic()
        {
            JsonResult<VerCodePicViewModel> result = new JsonResult<VerCodePicViewModel>();
            result.code = 1;
            result.msg = "OK";
            try
            {
                ClassLoger.Info("VerCodePic","開始獲取成語");
                cy_dictBll cybll = new cy_dictBll();
                IList<cy_dict> cylist = cybll.GetAllcy_dict();
                ClassLoger.Info("VerCodePic", cylist.Count.ToString());
                int i = Utils.GetRandom(0, cylist.Count-1);
                ClassLoger.Info("VerCodePic",i.ToString());
                cy_dict cy = cylist[i];
                ClassLoger.Info("VerCodePic成語:",cy.chengyu);
                VerCodePicViewModel vcvm = new VerCodePicViewModel();

                string sourcePic = FileHelper.GetVerCodePicResource();
                if (sourcePic.IsNull() || !File.Exists(sourcePic))
                {
                    sourcePic = @"E:\WebResources\images\VerCodePicSource\1.jpg";
                }
                ClassLoger.Info("VerCodePic圖片",sourcePic);
                VerCodePic codepic = FileHelper.GetVerCodePic(cy.chengyu, sourcePic);
                vcvm.content = cy.chengyu;
                vcvm.MainPic = codepic.PicURL;
                result.Result = vcvm;

                string key = cookieKey();
                RedisBase.Item_Set(key, codepic);
                RedisBase.ExpireEntryAt(key,DateTime.Now.AddMinutes(10));
                result.ResultMsg = key;
            } catch (Exception ex)
            {
                ClassLoger.Error("AccountController.VerCodePic",ex);
                result.code = -1;
                result.msg = "AccountController.VerCodePic發生異常:"+ex.Message;
            }
            return result;
        }

效果如圖:

圖片驗證碼校驗介面參數結構

public class CheckPicCodeViewModel
    {
        /// <summary>
        /// 客戶端令牌
        /// </summary>
        public string token { get; set; }

        public double x1 { get; set; }

        public double x2 { get; set; }

        public double x3 { get; set; }

        public double x4 { get; set; }

        public double y1 { get; set; }

        public double y2 { get; set; }

        public double y3 { get; set; }

        public double y4 { get; set; }
    }

驗證碼校驗介面

/// <summary>
        /// 校驗圖片驗證碼是否正確
        /// </summary>
        /// <param name="piccode"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("checkpiccode")]
        public async Task<IHttpActionResult> CheckPicCode([FromBody]CheckPicCodeViewModel piccode)
        {
            JsonResult<bool> result = new JsonResult<bool>();
            result.code = 1;
            result.msg = "OK";
            if (piccode == null)
            {
                result.Result = false;
                result.ResultMsg = "參數錯誤";
                return Ok(result);
            }
            if (string.IsNullOrEmpty(piccode.token) || !RedisBase.ContainsKey(piccode.token))
            {
                result.Result = false;
                result.ResultMsg = "驗證碼已過期";
                return Ok(result);
            }
            result.Result = await Task.Run<bool>(() => {
                bool flag = false;
                VerCodePic codepic = RedisBase.Item_Get<VerCodePic>(piccode.token);
                if (Math.Abs(codepic.Font1.X - piccode.x1) > 0.5 || Math.Abs(codepic.Font1.Y - piccode.y1) > 0.5
                    || Math.Abs(codepic.Font2.X - piccode.x2) > 0.5 || Math.Abs(codepic.Font2.Y - piccode.y2) > 0.5
                    || Math.Abs(codepic.Font3.X - piccode.x3) > 0.5 || Math.Abs(codepic.Font3.Y - piccode.y3) > 0.5
                    || Math.Abs(codepic.Font4.X - piccode.x4) > 0.5 || Math.Abs(codepic.Font4.Y - piccode.y4) > 0.5)
                {
                    flag = false;
                    result.ResultMsg = "驗證碼錯誤";
                }
                else
                {
                    flag = true;
                    result.ResultMsg = "驗證碼正確";
                }
                return flag;
            });
            return Ok(result);
        }

傳入用戶選中的位置和順序,並對其進行驗證


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.linux的目錄結構 bin:(binaries)存放二進位可執行文件 sbin(super user binaries)存放二進位可執行文件 etc:(etcetera)存放系統配置文件 usr(unix shared resources)用於存放共用的系統資源 home存放用戶文件的根目錄 ...
  • centos源更換為,163或者阿裡的。 1、首先備份 mv /etc/yum.repos.d/Centos Base.repo /etc/yum.repos.d/Centos Base.repo.backup 2、下載repo文件到目錄下 cd /etc/yum.repos.d wget http ...
  • 編譯windows下chromium,時間:20170619, 官方地址:https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md 一. 系統要求: 1. 64位機器,至少8G ...
  • 自助命令:ls --help man ls info ls 文件屬性:ls -al 顯示當前目錄下文件/目錄擁有者,所屬組,其他人的寫讀執行許可權 文件或目錄下屬文件數 擁有者 群組 內容大小(byte) 最後修改日期 文件/目錄名 註意:對於目錄,如何沒有x許可權,則進不去目錄 【顯示別的目錄下的文件 ...
  • 輸入:top PID 進程的ID USER 進程所有者 PR 進程的優先順序別,越小越優先被執行 Ninice 值 VIRT 進程占用的虛擬記憶體 RES 進程占用的物理記憶體 SHR 進程使用的共用記憶體 S 進程的狀態。S表示休眠,R表示正在運行,Z表示僵死狀態,N表示該進程優先值為負數 %CPU 進程 ...
  • 不想用實體機,想不想弄個快速的Android虛擬環境,今天我們就來說說把Android模擬器(RemixOS)安到Hyper-v上的辦法。 1. 下載RemixOs 或者直接去 論壇獲得下載地址 2. 在Hyper-v中創建第1代的虛擬機,50G硬碟,2G記憶體。別急著開機。 3. 在電腦管理中打開 ...
  • 沒什麼新的內容,自己的練習代碼,供大家點評。 ...
  • 問題原因可能是: 1. 非空列未插入值錯誤 2. 多個表間外鍵列長度不一樣 3. ef上下文對象db為空 4. ef上下文設置屬性為 db.Configuration.ValidateOnSaveEnabled = false; 5. 內容長度超過列最大長度 6.解決方案里後來新增了類庫但未更新 7 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...