asp.net點(diǎn)選驗(yàn)證碼實(shí)現(xiàn)思路分享 (附demo)
哈哈好久沒(méi)冒泡了,最進(jìn)看見(jiàn)點(diǎn)選驗(yàn)證碼有點(diǎn)意思,所以想自己寫一個(gè)。
先上效果圖

如果你被這個(gè)效果吸引了就請(qǐng)繼續(xù)看下去。
貼代碼前先說(shuō)點(diǎn)思路:
1.要有一個(gè)漢字庫(kù),并按字形分類。(我在數(shù)據(jù)庫(kù)里是安部首分類的)
2.獲取驗(yàn)證碼(也就是取幾個(gè)文字做驗(yàn)證碼)
3.根據(jù)取出來(lái)的文字去找形近字
4.排列驗(yàn)證碼文字和形近字
5.繪制圖片
6.顯示
一、獲取字庫(kù)
我國(guó)文化博大精深,辣么多的字從哪兒來(lái)?當(dāng)然我不可能手動(dòng)加進(jìn)去,于是我就在網(wǎng)上隨便找了一個(gè)能查漢字的網(wǎng)站,去抓別人的數(shù)據(jù)。抓數(shù)據(jù)的方法請(qǐng)點(diǎn)傳送門。傳送門里說(shuō)的只是思路,如果有不明白的請(qǐng)艾特我。我會(huì)在下面共享我的字庫(kù)。
二、獲取驗(yàn)證碼
這個(gè)就比較簡(jiǎn)單了這里我就直接貼代碼了,下面的代碼就是隨機(jī)排序后取4條數(shù)據(jù),我這樣寫是為了圖方便。個(gè)人覺(jué)得先隨機(jī)生成ID,然后直接根據(jù)ID取數(shù)據(jù),這樣查詢速度會(huì)比下面這種寫法快。(注意我用的數(shù)據(jù)庫(kù)是MySql)
/// <summary>
/// 獲取驗(yàn)證碼
/// </summary>
public List<VerificationCode.Model.WenZhi> GetCodeText()
{
const string sql = "SELECT * FROM wenzhi ORDER BY RAND() LIMIT 4";
var dataReader = dbHelper.GetDataReader(sql);
var list = DataReaderToList(dataReader);
dataReader.Close();
return list;
}
三、根據(jù)取出來(lái)的文字去找形近字
因?yàn)榈谝徊降臅r(shí)候我存部首了,所以這里我直接根據(jù)部首取獲取當(dāng)前部首的形近字。
/// <summary>
/// 獲取答案?jìng)溥x
/// </summary>
/// <param name="buShouCode">部首編碼</param>
/// <param name="id">當(dāng)前文字ID</param>
/// <param name="number">數(shù)量</param>
/// <returns></returns>
public List<VerificationCode.Model.WenZhi> GetAnswer(string buShouCode, int id,int number=1)
{
string sql = $"SELECT * FROM wenzhi where BuShouCode='{buShouCode}' and ID <> {id} ORDER BY RAND() LIMIT "+ number;
var dataReader = dbHelper.GetDataReader(sql);
var list = DataReaderToList(dataReader);
dataReader.Close();
return list;
}
四.排列驗(yàn)證碼文字和形近字
下面的代碼是先把備選答案和驗(yàn)證碼放在一個(gè)集合里然后再對(duì)集合排序
public Model.Code GetCode()
{
var wenzlist = _wenZhiDal.GetCodeText(); //獲取驗(yàn)證碼
var listAnsuwr = new List<Answer>();//實(shí)例化備選答案對(duì)象
var answerCode = string.Empty;//答案
var result = new Model.Code
{
Id = Guid.NewGuid().ToString()
};
//根據(jù)驗(yàn)證碼獲取備選答案并把添加到答案添加到備選答案集合
foreach (var item in wenzlist)
{
answerCode += item.ID + ",";
result.AnswerValue += item.Text;
var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID);
listAnsuwr.Add(new Answer { Id = item.ID.ToString(), Img = GetImage(item.Text) });
listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
}
//如果答案?jìng)€(gè)數(shù)不夠就再去取幾個(gè)
if (listAnsuwr.Count < 9)
{
var ran = new Random();
var randKey = ran.Next(0, 4);
var item = wenzlist[randKey];
var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID, 9 - listAnsuwr.Count);
listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
}
result.CodeImg = GetImage(result.AnswerValue);//獲取圖片
result.AnswerValue = answerCode.TrimEnd(',');
result.Answer = RandomSortList(listAnsuwr);//打亂正確答案與形近字的順序
return result;
}
這是對(duì)集合排序的代碼
/// <summary>
/// 隨機(jī)排列集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="listT"></param>
/// <returns></returns>
private static List<T> RandomSortList<T>(IEnumerable<T> listT)
{
var random = new Random();
var newList = new List<T>();
foreach (var item in listT)
{
newList.Insert(random.Next(newList.Count + 1), item);
}
return newList;
}
五、繪制圖片
下面是畫圖的代碼,驗(yàn)證碼和備選答案對(duì)應(yīng)兩種不同的畫法(里面注釋寫的還算清楚)。不要擔(dān)心文字旋轉(zhuǎn)x°后人類分不出來(lái),哈哈。代碼最后一句我把圖片轉(zhuǎn)成了Base64,方便前端調(diào)用。
private static string GetImage(string text)
{
Image image;
switch (text.Length)
{
case 1:
image = new Bitmap(50, 40);
break;
case 4:
image = new Bitmap(120, 40);
break;
default:
image = new Bitmap(50, 40);
break;
}
Brush brushText = new SolidBrush(Color.FromArgb(255, 0, 0, 0));
var graphics = Graphics.FromImage(image);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.Clear(Color.White);
var font = new Font(new FontFamily("華文彩云"), 20, FontStyle.Regular);
if (text.Length > 1)//畫驗(yàn)證碼
{
//先來(lái)兩條直線做干擾 然后再畫文字
graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(0, 10), new Random().Next(10, 40)), new Point(new Random().Next(100, 120), new Random().Next(10, 30)));
graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(20, 50), new Random().Next(0, 10)), new Point(new Random().Next(100, 120), new Random().Next(30, 40)));
graphics.DrawString(text, font, brushText, 0, 10);
}
else//畫備選答案
{
Point middle = new Point(25, 20);
graphics.TranslateTransform(middle.X, middle.Y);
//這里是360°隨機(jī)旋轉(zhuǎn)
graphics.RotateTransform(new Random().Next(0, 360));
var format = new StringFormat(StringFormatFlags.NoClip)
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
graphics.DrawString(text, font, brushText, 0, 0, format);
}
brushText.Dispose();
graphics.Dispose();
return ImageToBase64(image);
}
六、顯示
直接調(diào)用GetCode方法就能返回驗(yàn)證碼對(duì)象
下面是后臺(tái)代碼,應(yīng)為正確答案是放在AnswerValue里的所以我先把取出來(lái)放Session里面,然后把值清空后再通過(guò)json返回給瀏覽器。
public string GetVerCode()
{
var code = new VerificationCode.Code().GetCode();
Session["VERCODE"] = code.AnswerValue;
code.AnswerValue = "";
return JsonConvert.SerializeObject(code);
}
現(xiàn)在來(lái)堆點(diǎn)html代碼
<div class="form-group">
<ul class="vercode">
<li><img src=''/></li>
<li><img src=''/></li>
<li><img src=''/></li>
<li><img src=''/></li>
<li class="delete" onclick="delete_input()"></li>
</ul>
<div>
<img id="code-image"/> <a href="javascript:void(0);" onclick="load_vercode()">看不清?</a>
</div>
<ul class="vercode-anwser">
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
<li><img /></li>
</ul>
</div>
再來(lái)點(diǎn)js代碼,這里只實(shí)現(xiàn)的圖片上的效果,還沒(méi)對(duì)數(shù)據(jù)驗(yàn)證(這里說(shuō)說(shuō)驗(yàn)證思路:每個(gè)圖片對(duì)應(yīng)一個(gè)ID,取到選擇圖片的ID用逗號(hào)分隔,然后與Session里的值對(duì)比)
<script>
$(function () {
//加載驗(yàn)證碼
load_vercode();
//綁定驗(yàn)證碼點(diǎn)擊事件
$(".vercode-anwser").find("img").on("click", null, function () {
$(".vercode").find("img[src='']:eq(0)").attr("src", $(this).attr("src"));
});
});
function load_vercode() {
$(".vercode").find("img").attr("src", "");
$.get("GetVerCode", function (data) {
var result = JSON.parse(data);
$("#code-image").attr("src", "data:image/png;base64," + result.CodeImg);
$(".vercode-anwser").find("img").each(function (index) {
$(this).attr("src", "data:image/png;base64," + result.Answer[index].Img);
});
});
}
//刪除事件
function delete_input() {
$(".vercode").find("img[src!='']:last").attr("src", "");
}
</script>
到這里代碼就差不多了,以上思路只是單純的個(gè)人想法,有興趣的朋友一起來(lái)討論吧。
源代碼在這里-->地址 http://xiazai.jb51.net/201701/yuanma/VerificationCode_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Asp.net Web Api實(shí)現(xiàn)圖片點(diǎn)擊式圖片驗(yàn)證碼功能
- 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?Api?中使用Elasticsearch存儲(chǔ)文檔的方法
Elasticsearch 是一個(gè)分布式、高擴(kuò)展、高實(shí)時(shí)的搜索與數(shù)據(jù)分析引擎,在C# 的環(huán)境中,有一個(gè)Es的官方拓展包Nest,可以讓我們方便快捷的使用上Es數(shù)據(jù)庫(kù),本文重點(diǎn)給大家介紹.Net?Api?中使用Elasticsearch存儲(chǔ)文檔的方法,感興趣的朋友一起看看吧2022-01-01
ASP.NET讓FileUpload控件支持瀏覽自動(dòng)上傳功能的解決方法
這篇文章主要介紹了ASP.NET讓FileUpload控件支持瀏覽自動(dòng)上傳功能的解決方法,很實(shí)用的技巧,需要的朋友可以參考下2014-07-07
WPF項(xiàng)目在設(shè)計(jì)界面調(diào)用后臺(tái)代碼
這篇文章介紹了WPF項(xiàng)目在設(shè)計(jì)界面調(diào)用后臺(tái)代碼的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
詳解ASP.NET MVC 常用擴(kuò)展點(diǎn):過(guò)濾器、模型綁定
本篇文章主要介紹了詳解ASP.NET MVC 常用擴(kuò)展點(diǎn):過(guò)濾器、模型綁定,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05
asp.net 簡(jiǎn)便無(wú)刷新文件上傳系統(tǒng)
之前寫過(guò)一個(gè)仿163網(wǎng)盤無(wú)刷新多文件上傳系統(tǒng),已經(jīng)對(duì)無(wú)刷新上傳文件的原理做了詳細(xì)的分析而這次的系統(tǒng)主要是針對(duì)單個(gè)file控件的,便攜版,使用更簡(jiǎn)單,還有更深入的分析2012-05-05
在WinForm和WPF中使用GMap.Net地圖插件簡(jiǎn)單教程
GMap.NET是一個(gè)強(qiáng)大、免費(fèi)、跨平臺(tái)、開源的.NET控件,它在Windows Forms 和WPF環(huán)境中能夠使用來(lái)自Google, Yahoo!, Bing, OpenStreetMap, ArcGIS, Pergo, SigPac等地圖,下面看一下使用方法2013-12-12
完美解決Could not load file or assembly AjaxPro.2 or one of its
Could not load file or assembly AjaxPro.2,經(jīng)排查原來(lái)是mcafee限制了2007-08-08

