Asp.net Web Api實(shí)現(xiàn)圖片點(diǎn)擊式圖片驗(yàn)證碼功能
現(xiàn)在驗(yàn)證碼的形式越來越豐富,今天要實(shí)現(xiàn)的是在點(diǎn)擊圖片中的文字來進(jìn)行校驗(yàn)的驗(yàn)證碼,如圖

這種驗(yàn)證碼驗(yàn)證是驗(yàn)證鼠標(biāo)是否選中了圖片中文字的位置,以及選擇的順序,產(chǎn)生驗(yàn)證碼的時(shí)候可以提供一組底圖,然后隨機(jī)獲取一張圖片,隨機(jī)選取幾個(gè)字,然后把文字的順序打亂,分別隨機(jī)放到圖片的一個(gè)位置上,然后記錄文字的位置和順序,驗(yàn)證的時(shí)候驗(yàn)證一下文字的位置和順序即可
驗(yàn)證碼圖片的類
/// <summary>
/// 二維碼圖片
/// </summary>
public class VerCodePic
{
/// <summary>
/// 圖片鏈接
/// </summary>
public string PicURL { get; set; }
/// <summary>
/// 第一個(gè)字位置
/// </summary>
public FontPoint Font1 { get; set; }
/// <summary>
/// 第二個(gè)字位置
/// </summary>
public FontPoint Font2 { get; set; }
/// <summary>
/// 第三個(gè)字位置
/// </summary>
public FontPoint Font3 { get; set; }
/// <summary>
/// 第四個(gè)字位置
/// </summary>
public FontPoint Font4 { get; set; }
}
/// <summary>
/// 文字位置
/// </summary>
public class FontPoint
{
public int X { get; set; }
public int Y { get; set; }
}
生成驗(yàn)證碼圖片驗(yàn)證碼的方法,在這個(gè)方法中指定了生成的驗(yàn)證碼圖片中字體大小為20個(gè)像素,因?yàn)轵?yàn)證碼底圖的大小是固定的,所以就把驗(yàn)證碼底圖按照字體的大小分成了若干個(gè)網(wǎng)格位置,指定一個(gè)文字在圖片中的位置時(shí)只需要隨機(jī)獲取其中一個(gè)網(wǎng)格即可,如果這個(gè)網(wǎng)格中沒有指定過文字,那就把文字放到這個(gè)網(wǎng)格中。
提前設(shè)定網(wǎng)格的方法
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;
}
}
我選定的驗(yàn)證碼底圖為280*100的,所以按照上邊的方法將圖片分成了若干個(gè)網(wǎng)格,在下邊設(shè)定一個(gè)文字位置的時(shí)候隨機(jī)選取其中一個(gè)位置,而且給每個(gè)字都設(shè)定了不一樣的顏色
/// <summary>
/// 根據(jù)文字和圖片獲取驗(yàn)證碼圖片
/// </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;
}
獲取圖片驗(yàn)證碼的api接口,在這個(gè)接口中從成語庫中隨機(jī)選取了一個(gè)成語,然后隨機(jī)選取了一個(gè)圖片,然后調(diào)用生成圖片驗(yàn)證碼的方法,生成了圖片驗(yàn)證碼,并且把驗(yàn)證碼對(duì)應(yīng)的信息緩存在redis中,設(shè)定緩存時(shí)間,將redis的key作為一個(gè)臨時(shí)令牌隨同驗(yàn)證碼返回
/// <summary>
/// 獲取驗(yàn)證碼,有效時(shí)間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發(fā)生異常:"+ex.Message;
}
return result;
}
效果如圖:

圖片驗(yàn)證碼校驗(yàn)接口參數(shù)結(jié)構(gòu)
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; }
}
驗(yàn)證碼校驗(yàn)接口
/// <summary>
/// 校驗(yàn)圖片驗(yàn)證碼是否正確
/// </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 = "參數(shù)錯(cuò)誤";
return Ok(result);
}
if (string.IsNullOrEmpty(piccode.token) || !RedisBase.ContainsKey(piccode.token))
{
result.Result = false;
result.ResultMsg = "驗(yàn)證碼已過期";
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 = "驗(yàn)證碼錯(cuò)誤";
}
else
{
flag = true;
result.ResultMsg = "驗(yàn)證碼正確";
}
return flag;
});
return Ok(result);
}
傳入用戶選中的位置和順序,并對(duì)其進(jìn)行驗(yàn)證。
以上所述是小編給大家介紹的Asp.net Web Api實(shí)現(xiàn)圖片點(diǎn)擊式圖片驗(yàn)證碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- asp.net點(diǎn)選驗(yàn)證碼實(shí)現(xiàn)思路分享 (附demo)
- ASP.NET中畫圖形驗(yàn)證碼的實(shí)現(xiàn)代碼
- Asp.net開發(fā)之webform圖片水印和圖片驗(yàn)證碼的實(shí)現(xiàn)方法
- asp.net登錄驗(yàn)證碼實(shí)現(xiàn)方法
- asp.net之生成驗(yàn)證碼的方法集錦(一)
- 如何使用ASP.NET制作簡(jiǎn)單的驗(yàn)證碼
- asp.net驗(yàn)證碼圖片生成示例
- ASP.NET 實(shí)現(xiàn)驗(yàn)證碼以及刷新驗(yàn)證碼的小例子
- Asp.net實(shí)現(xiàn)手寫驗(yàn)證碼的操作代碼
相關(guān)文章
.NET Core對(duì)象池的應(yīng)用:設(shè)計(jì)篇
本文主要講解對(duì)象池的三個(gè)核心對(duì)象:表示對(duì)象池的ObjectPool<T>對(duì)象、對(duì)象值提供者的ObjectPoolProvider對(duì)象,已及控制池化對(duì)象創(chuàng)建與釋放行為的IPooledObjectPolicy<T>對(duì)象。感興趣的小伙伴可以參考一下這篇文章2021-09-09
asp.net實(shí)現(xiàn)的MVC跨數(shù)據(jù)庫多表聯(lián)合動(dòng)態(tài)條件查詢功能示例
這篇文章主要介紹了asp.net實(shí)現(xiàn)的MVC跨數(shù)據(jù)庫多表聯(lián)合動(dòng)態(tài)條件查詢功能,結(jié)合實(shí)例形式較為詳細(xì)分析了asp.net基于MVC架構(gòu)的跨數(shù)據(jù)庫多表聯(lián)合查詢功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02
ubuntu16.4下用jexus部署ASP.NET Core環(huán)境
這篇文章主要以圖文結(jié)合的方式介紹了ubuntu16.4下ASP.NET Core部署環(huán)境搭建步驟,感興趣的小伙伴們可以參考一下2016-07-07
CheckBox控件默認(rèn)選中,提交時(shí)永遠(yuǎn)獲得選中狀態(tài)的實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄狢heckBox控件默認(rèn)選中,提交時(shí)永遠(yuǎn)獲得選中狀態(tài)的實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05
MAUI項(xiàng)目中使用SnackBar與Toast通知功能
這篇文章介紹了MAUI項(xiàng)目中使用SnackBar與Toast通知功能的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02
關(guān)于.net(C#)中的跨進(jìn)程訪問的問題
C# 跨進(jìn)程訪問實(shí)現(xiàn)代碼。2009-04-04
獲取WebService的請(qǐng)求信息方法實(shí)例
下面小編就為大家分享一篇獲取WebService的請(qǐng)求信息方法實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11

