ASP.NET CORE 项目实战 ---图形验证码的实现
簡介
很長時間沒有來更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其實(shí)已經(jīng)完成了一個框架了,并且正在準(zhǔn)備在生產(chǎn)環(huán)境中試用,但是很多東西也是出于自己理解的膚淺和技術(shù)的不斷更新,經(jīng)常變動,所以,如果自己還沒有完全搞好,就來寫博客,反復(fù)的修正,可能會誤導(dǎo)一些新手朋友。
如果有正在研究Core的朋友,可以大家一起交流下。?
?
驗(yàn)證碼
相信很多朋友跟我一樣,圖形驗(yàn)證碼成為了 Core 的一個絆腳石。?
System.Drawing.Primitives 這是官方的一個Drawing庫,但是沒有Bitmap、Graphics等很多東西,所以這個做圖形驗(yàn)證碼基本Pass了。?
? ?CoreCompat.System.Drawing 這個是一個第三方的,使用了mono的System.Drawing實(shí)現(xiàn),只要安裝了之前使用System.Drawing的代碼完全不用修改,也支持描畫驗(yàn)證碼等描畫類的功能。如果需要linux或osx支持,可以安裝runtime.linux.CoreCompat.System.Drawing和runtime.osx.10.10-x64.CoreCompat.System.Drawing。(地址:https://github.com/CoreCompat/CoreCompat),基本大家都是在用這個吧,這個在Windows下是沒有任何問題的,在Linux上一直沒有成功,也不知道是自己編譯的問題還是什么問題。?
? zkweb.system.drawing 這個也是第三方的,從mono的System.Drawing修改得來的。過程比較詳細(xì),也實(shí)現(xiàn)了。所以把這個的使用跟大家分享一下。?
這個類庫和CoreCompat的不同點(diǎn)如下?
沒有使用強(qiáng)名稱,CoreCompat為了讓程序集名稱一樣使用了一個偽造的簽名,但是導(dǎo)致Asp.Net和Owin等會檢查簽名的舊項(xiàng)目啟動失敗
CoreCompat的項(xiàng)目如果直接下載編譯會出現(xiàn)100多個錯誤,大多是類型找不到的錯誤,我也不知道作者是怎么編譯過去的
這個項(xiàng)目從mono 4.6.1.13復(fù)制了所有需要的文件并修改,直接下載編譯就可以通過可以使用dotnet test跑單元測試,目前通過率約為80%
實(shí)際在linux上測試過并且給出了各個發(fā)行版安裝libgdiplus的命令,目前已測試不引用System.Drawing.Primitive,因?yàn)镾ystem.Drawing.Primitive在.Net Framework下同時引用了原來的System.Drawing,有可能導(dǎo)致編譯時類型沖突(實(shí)測只有警告)
Ubuntu Server 16.04 LTS 64bit
Fedora 24 64bit
CentOS 7.2 64bit
??
Zkweb.system.drawing
首先通過Nuget:?Install-Package ZKWeb.System.Drawing?添加 引用
?
?
簡單的圖形驗(yàn)證碼生成:
?
public class VierificationCodeServices
? ? {
? ? ? ? /// <summary> ?
? ? ? ? /// 該方法用于生成指定位數(shù)的隨機(jī)數(shù) ?
? ? ? ? /// </summary> ?
? ? ? ? /// <param name="VcodeNum">參數(shù)是隨機(jī)數(shù)的位數(shù)</param> ?
? ? ? ? /// <returns>返回一個隨機(jī)數(shù)字符串</returns> ?
? ? ? ? private string RndNum(int VcodeNum)
? ? ? ? {
? ? ? ? ? ? //驗(yàn)證碼可以顯示的字符集合 ?
? ? ? ? ? ? string Vchar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p" +
? ? ? ? ? ? ? ? ",q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,P,P,Q" +
? ? ? ? ? ? ? ? ",R,S,T,U,V,W,X,Y,Z";
? ? ? ? ? ? string[] VcArray = Vchar.Split(new Char[] { ',' });//拆分成數(shù)組 ??
? ? ? ? ? ? string code = "";//產(chǎn)生的隨機(jī)數(shù) ?
? ? ? ? ? ? int temp = -1;//記錄上次隨機(jī)數(shù)值,盡量避避免生產(chǎn)幾個一樣的隨機(jī)數(shù) ?
? ? ? ? ? ? Random rand = new Random();
? ? ? ? ? ? //采用一個簡單的算法以保證生成隨機(jī)數(shù)的不同 ?
? ? ? ? ? ? for (int i = 1; i < VcodeNum + 1; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (temp != -1)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));//初始化隨機(jī)類 ?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? int t = rand.Next(61);//獲取隨機(jī)數(shù) ?
? ? ? ? ? ? ? ? if (temp != -1 && temp == t)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? return RndNum(VcodeNum);//如果獲取的隨機(jī)數(shù)重復(fù),則遞歸調(diào)用 ?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? temp = t;//把本次產(chǎn)生的隨機(jī)數(shù)記錄起來 ?
? ? ? ? ? ? ? ? code += VcArray[t];//隨機(jī)數(shù)的位數(shù)加一 ?
? ? ? ? ? ? }
? ? ? ? ? ? return code;
? ? ? ? }
? ? ? ? /// <summary> ?
? ? ? ? /// 該方法是將生成的隨機(jī)數(shù)寫入圖像文件 ?
? ? ? ? /// </summary> ?
? ? ? ? /// <param name="code">code是一個隨機(jī)數(shù)</param>
? ? ? ? /// <param name="numbers">生成位數(shù)(默認(rèn)4位)</param> ?
? ? ? ? public MemoryStream Create(out string code, int numbers = 4)
? ? ? ? {
? ? ? ? ? ? code = RndNum(numbers);
? ? ? ? ? ? Bitmap Img = null;
? ? ? ? ? ? Graphics g = null;
? ? ? ? ? ? MemoryStream ms = null;
? ? ? ? ? ? Random random = new Random();
? ? ? ? ? ? //驗(yàn)證碼顏色集合 ?
? ? ? ? ? ? Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
? ? ? ? ? ? //驗(yàn)證碼字體集合
? ? ? ? ? ? string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋體" };
? ? ? ? ? ? //定義圖像的大小,生成圖像的實(shí)例 ?
? ? ? ? ? ? Img = new Bitmap((int)code.Length * 18, 32);
? ? ? ? ? ? g = Graphics.FromImage(Img);//從Img對象生成新的Graphics對象 ? ?
? ? ? ? ? ? g.Clear(Color.White);//背景設(shè)為白色 ?
? ? ? ? ? ? //在隨機(jī)位置畫背景點(diǎn) ?
? ? ? ? ? ? for (int i = 0; i < 100; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int x = random.Next(Img.Width);
? ? ? ? ? ? ? ? int y = random.Next(Img.Height);
? ? ? ? ? ? ? ? g.DrawRectangle(new Pen(Color.LightGray, 0), x, y, 1, 1);
? ? ? ? ? ? }
? ? ? ? ? ? //驗(yàn)證碼繪制在g中 ?
? ? ? ? ? ? for (int i = 0; i < code.Length; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int cindex = random.Next(7);//隨機(jī)顏色索引值 ?
? ? ? ? ? ? ? ? int findex = random.Next(5);//隨機(jī)字體索引值 ?
? ? ? ? ? ? ? ? Font f = new Font(fonts[findex], 15, FontStyle.Bold);//字體 ?
? ? ? ? ? ? ? ? Brush b = new SolidBrush(c[cindex]);//顏色 ?
? ? ? ? ? ? ? ? int ii = 4;
? ? ? ? ? ? ? ? if ((i + 1) % 2 == 0)//控制驗(yàn)證碼不在同一高度 ?
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ii = 2;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? g.DrawString(code.Substring(i, 1), f, b, 3 + (i * 12), ii);//繪制一個驗(yàn)證字符 ?
? ? ? ? ? ? }
? ? ? ? ? ? ms = new MemoryStream();//生成內(nèi)存流對象 ?
? ? ? ? ? ? Img.Save(ms, ImageFormat.Jpeg);//將此圖像以Png圖像文件的格式保存到流中 ?
? ? ? ? ? ? //回收資源 ?
? ? ? ? ? ? g.Dispose();
? ? ? ? ? ? Img.Dispose();
? ? ? ? ? ? return ms;
? ? ? ? }
? ? }
測試運(yùn)行?
在Controller中新建一個 IActionResult 用于輸出驗(yàn)證碼:
/// <summary>
? ? ? ? /// 圖形驗(yàn)證碼
? ? ? ? /// </summary>
? ? ? ? /// <returns></returns>
? ? ? ? public IActionResult ValidateCode([FromServices]VierificationCodeServices _vierificationCodeServices)
? ? ? ? {
? ? ? ? ? ? string code = "";
? ? ? ? ? ? System.IO.MemoryStream ms = _vierificationCodeServices.Create(out code);
? ? ? ? ? ? HttpContext.Session.SetString("LoginValidateCode", code);
? ? ? ? ? ? Response.Body.Dispose();
? ? ? ? ? ? return File(ms.ToArray(), @"image/png");
? ? ? ? }
前臺輸出:<img id="imgVerify" src="/sysmanage/account/ValidateCode" alt="看不清?點(diǎn)擊更換" οnclick="this.src = this.src + '?'" style="vertical-align:middle;" />
?Windows
?
我們在Windows下運(yùn)行一下:
?
Linux(CentOS7)
?
我們按照步驟,執(zhí)行以下命令:
?yum install autoconf automake libtool
?yum install freetype-devel fontconfig libXft-devel
?yum install libjpeg-turbo-devel libpng-devel giflib-devel libtiff-devel libexif-devel
?yum install glib2-devel cairo-devel
?git clone https://github.com/mono/libgdiplus
?cd libgdiplus
?./autogen.sh
?make
?make install
?cd /usr/lib64/
?ln -s /usr/local/lib/libgdiplus.so gdiplus.dll
?
?把我們發(fā)布好的項(xiàng)目上傳到Linux服務(wù)器上,進(jìn)入項(xiàng)目目錄:
cd OcelotWeb
dotnet Ocelot.Web.dll
?
?
我們的打開網(wǎng)站看一下:
?
沒有顯示出來,我們看下運(yùn)行的日志:
?
FontFamily Not Found,字體的錯誤,我們看一下我們的代碼:
?
這些字體Linux沒有,這個解決辦法很多,這里我用了最簡單的,我不想再去修改我的代碼,我就直接把windows下的這些字體拷貝出來:
上傳到服務(wù)器的?/usr/share/fonts/chinese/TrueType?目錄下(chinese/TrueType 兩個目錄是自己創(chuàng)建的)
進(jìn)入這個目錄:
cd /usr/share/fonts/chinese/TrueType
mkfontscale
mkfontdir
?fc-cache -fv
再次打開之前的頁面:
?
?出現(xiàn)了!
原文地址:http://www.cnblogs.com/yuangang/p/6000460.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的ASP.NET CORE 项目实战 ---图形验证码的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net Core上用于代替System
- 下一篇: asp.net ajax控件工具集 Au