日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 生成验证码

發(fā)布時間:2023/12/4 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 生成验证码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊藍字

關注我

使用驗證碼保護網站免受垃圾信息的選擇有很多,比如Google ReCaptchacaptcha.com。這兩者都可以整合到ASP.NET Core應用中去。然而,如果你出于某些原因,仍然希望自己寫驗證碼,例如你下網站需要在中國大陸使用,那么本文會教你如何在最新版的ASP.NET Core中生成和使用驗證碼。

我所使用的方法是在微軟樣例代碼庫??https://code.msdn.microsoft.com/How-to-make-and-use-d0d1752a 的基礎之上做了一些修改,以運行于.NET Core 2.x上,并也有一些改進。

驗證碼是如何工作的

一個簡單的驗證碼原理是生成一串隨機字符(數(shù)字或字母),將字符串保存到Session中,同時生成一張圖片用來顯示在網頁上。當用戶提交內容到服務器的時,服務器檢查用戶輸入的驗證碼是否與Session中的一致,以此判斷驗證碼是否正確。流程如下圖:

這個樣例是我下一版本博客中的驗證碼:

在 ASP.NET Core 2.1 中實現(xiàn)驗證碼

在了解驗證碼工作流程之后,我們來看看如何實現(xiàn)。

1

準備工作

首先,你需要在工程屬性的DebugRelease模式里都勾選"Allow unsafe code"。

我們需要使用?System.Drawing.Imaging 命名空間里的類型,所以我們也需要安裝一個NuGet包:

Install-Package System.Drawing.Common -Version 4.5.1

因為驗證碼依賴Session存儲,所以我們也需要在ASP.NET Core中啟用Session支持。在Startup.cs里加入:

public void ConfigureServices(IServiceCollection services)

{

? ? // other code...

? ??

? ? // add session support

? ? services.AddSession(options =>

? ? {

? ? ? ? options.IdleTimeout = TimeSpan.FromMinutes(20);

? ? ? ? options.Cookie.HttpOnly = true;

? ? });

? ? // other code...

}

還有這里:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

{

? ? // other code...

? ? // add session support

? ? app.UseSession();

? ? // other code...

}

注意:Session依賴Cookie才能工作,所以請確保用戶首先接受GDPR cookie策略,這是ASP.NET Core 2.1默認模板里添加的。

2

生成驗證碼

新建一個?CaptchaResult?類用來描述驗證碼信息:

public class CaptchaResult

{

? ? public string CaptchaCode { get; set; }

? ? public byte[] CaptchaByteData { get; set; }

? ? public string CaptchBase64Data => Convert.ToBase64String(CaptchaByteData);

? ? public DateTime Timestamp { get; set; }

}

以及一個Captcha類來生成并驗證驗證碼

public static class Captcha

{

? ? const string Letters = "2346789ABCDEFGHJKLMNPRTUVWXYZ";


? ? public static string GenerateCaptchaCode()

? ? {

? ? ? ? Random rand = new Random();

? ? ? ? int maxRand = Letters.Length - 1;


? ? ? ? StringBuilder sb = new StringBuilder();


? ? ? ? for (int i = 0; i < 4; i++)

? ? ? ? {

? ? ? ? ? ? int index = rand.Next(maxRand);

? ? ? ? ? ? sb.Append(Letters[index]);

? ? ? ? }


? ? ? ? return sb.ToString();

? ? }


? ? public static bool ValidateCaptchaCode(string userInputCaptcha, HttpContext context)

? ? {

? ? ? ? var isValid = userInputCaptcha == context.Session.GetString("CaptchaCode");

? ? ? ? context.Session.Remove("CaptchaCode");

? ? ? ? return isValid;

? ? }


? ? public static CaptchaResult GenerateCaptchaImage(int width, int height, string captchaCode)

? ? {

? ? ? ? using (Bitmap baseMap = new Bitmap(width, height))

? ? ? ? using (Graphics graph = Graphics.FromImage(baseMap))

? ? ? ? {

? ? ? ? ? ? Random rand = new Random();


? ? ? ? ? ? graph.Clear(GetRandomLightColor());


? ? ? ? ? ? DrawCaptchaCode();

? ? ? ? ? ? DrawDisorderLine();

? ? ? ? ? ? AdjustRippleEffect();


? ? ? ? ? ? MemoryStream ms = new MemoryStream();


? ? ? ? ? ? baseMap.Save(ms, ImageFormat.Png);


? ? ? ? ? ? return new CaptchaResult { CaptchaCode = captchaCode, CaptchaByteData = ms.ToArray(), Timestamp = DateTime.Now };


? ? ? ? ? ? int GetFontSize(int imageWidth, int captchCodeCount)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? var averageSize = imageWidth / captchCodeCount;


? ? ? ? ? ? ? ? return Convert.ToInt32(averageSize);

? ? ? ? ? ? }


? ? ? ? ? ? Color GetRandomDeepColor()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? int redlow = 160, greenLow = 100, blueLow = 160;

? ? ? ? ? ? ? ? return Color.FromArgb(rand.Next(redlow), rand.Next(greenLow), rand.Next(blueLow));

? ? ? ? ? ? }


? ? ? ? ? ? Color GetRandomLightColor()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? int low = 180, high = 255;


? ? ? ? ? ? ? ? int nRend = rand.Next(high) % (high - low) + low;

? ? ? ? ? ? ? ? int nGreen = rand.Next(high) % (high - low) + low;

? ? ? ? ? ? ? ? int nBlue = rand.Next(high) % (high - low) + low;


? ? ? ? ? ? ? ? return Color.FromArgb(nRend, nGreen, nBlue);

? ? ? ? ? ? }


? ? ? ? ? ? void DrawCaptchaCode()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? SolidBrush fontBrush = new SolidBrush(Color.Black);

? ? ? ? ? ? ? ? int fontSize = GetFontSize(width, captchaCode.Length);

? ? ? ? ? ? ? ? Font font = new Font(FontFamily.GenericSerif, fontSize, FontStyle.Bold, GraphicsUnit.Pixel);

? ? ? ? ? ? ? ? for (int i = 0; i < captchaCode.Length; i++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? fontBrush.Color = GetRandomDeepColor();


? ? ? ? ? ? ? ? ? ? int shiftPx = fontSize / 6;


? ? ? ? ? ? ? ? ? ? float x = i * fontSize + rand.Next(-shiftPx, shiftPx) + rand.Next(-shiftPx, shiftPx);

? ? ? ? ? ? ? ? ? ? int maxY = height - fontSize;

? ? ? ? ? ? ? ? ? ? if (maxY < 0) maxY = 0;

? ? ? ? ? ? ? ? ? ? float y = rand.Next(0, maxY);


? ? ? ? ? ? ? ? ? ? graph.DrawString(captchaCode[i].ToString(), font, fontBrush, x, y);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }


? ? ? ? ? ? void DrawDisorderLine()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Pen linePen = new Pen(new SolidBrush(Color.Black), 3);

? ? ? ? ? ? ? ? for (int i = 0; i < rand.Next(3, 5); i++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? linePen.Color = GetRandomDeepColor();


? ? ? ? ? ? ? ? ? ? Point startPoint = new Point(rand.Next(0, width), rand.Next(0, height));

? ? ? ? ? ? ? ? ? ? Point endPoint = new Point(rand.Next(0, width), rand.Next(0, height));

? ? ? ? ? ? ? ? ? ? graph.DrawLine(linePen, startPoint, endPoint);


? ? ? ? ? ? ? ? ? ? //Point bezierPoint1 = new Point(rand.Next(0, width), rand.Next(0, height));

? ? ? ? ? ? ? ? ? ? //Point bezierPoint2 = new Point(rand.Next(0, width), rand.Next(0, height));


? ? ? ? ? ? ? ? ? ? //graph.DrawBezier(linePen, startPoint, bezierPoint1, bezierPoint2, endPoint);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }


? ? ? ? ? ? void AdjustRippleEffect()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? short nWave = 6;

? ? ? ? ? ? ? ? int nWidth = baseMap.Width;

? ? ? ? ? ? ? ? int nHeight = baseMap.Height;


? ? ? ? ? ? ? ? Point[,] pt = new Point[nWidth, nHeight];


? ? ? ? ? ? ? ? for (int x = 0; x < nWidth; ++x)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? for (int y = 0; y < nHeight; ++y)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? var xo = nWave * Math.Sin(2.0 * 3.1415 * y / 128.0);

? ? ? ? ? ? ? ? ? ? ? ? var yo = nWave * Math.Cos(2.0 * 3.1415 * x / 128.0);


? ? ? ? ? ? ? ? ? ? ? ? var newX = x + xo;

? ? ? ? ? ? ? ? ? ? ? ? var newY = y + yo;


? ? ? ? ? ? ? ? ? ? ? ? if (newX > 0 && newX < nWidth)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? pt[x, y].X = (int)newX;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? pt[x, y].X = 0;

? ? ? ? ? ? ? ? ? ? ? ? }



? ? ? ? ? ? ? ? ? ? ? ? if (newY > 0 && newY < nHeight)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? pt[x, y].Y = (int)newY;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? pt[x, y].Y = 0;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? Bitmap bSrc = (Bitmap)baseMap.Clone();


? ? ? ? ? ? ? ? BitmapData bitmapData = baseMap.LockBits(new Rectangle(0, 0, baseMap.Width, baseMap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

? ? ? ? ? ? ? ? BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);


? ? ? ? ? ? ? ? int scanline = bitmapData.Stride;


? ? ? ? ? ? ? ? IntPtr scan0 = bitmapData.Scan0;

? ? ? ? ? ? ? ? IntPtr srcScan0 = bmSrc.Scan0;


? ? ? ? ? ? ? ? unsafe

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? byte* p = (byte*)(void*)scan0;

? ? ? ? ? ? ? ? ? ? byte* pSrc = (byte*)(void*)srcScan0;


? ? ? ? ? ? ? ? ? ? int nOffset = bitmapData.Stride - baseMap.Width * 3;


? ? ? ? ? ? ? ? ? ? for (int y = 0; y < nHeight; ++y)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? for (int x = 0; x < nWidth; ++x)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? var xOffset = pt[x, y].X;

? ? ? ? ? ? ? ? ? ? ? ? ? ? var yOffset = pt[x, y].Y;


? ? ? ? ? ? ? ? ? ? ? ? ? ? if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (pSrc != null)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p[0] = pSrc[yOffset * scanline + xOffset * 3];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p[1] = pSrc[yOffset * scanline + xOffset * 3 + 1];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p[2] = pSrc[yOffset * scanline + xOffset * 3 + 2];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? ? ? ? ? ? ? p += 3;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? p += nOffset;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? baseMap.UnlockBits(bitmapData);

? ? ? ? ? ? ? ? bSrc.UnlockBits(bmSrc);

? ? ? ? ? ? ? ? bSrc.Dispose();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

這么長的代碼你竟然看完了!

有一些要指出的地方:

1

字符集并不包含全部的字母和數(shù)字,這是因為有些數(shù)字和英文字母難以區(qū)分,比如:

  • 數(shù)字0和字母O

  • 數(shù)字5和字母S

  • 數(shù)字1和字母I

2

我注釋掉了DrawDisorderLine()方法中的貝塞爾曲線,這是因為當驗證碼圖片非常小的時候,貝塞爾曲線會干擾字符顯示,看不清驗證碼。

現(xiàn)在,在你的MVC控制器中,創(chuàng)建一個Action用于返回驗證碼圖片:

[Route("get-captcha-image")]

public IActionResult GetCaptchaImage()

{

? ? int width = 100;

? ? int height = 36;

? ? var captchaCode = Captcha.GenerateCaptchaCode();

? ? var result = Captcha.GenerateCaptchaImage(width, height, captchaCode);

? ? HttpContext.Session.SetString("CaptchaCode", result.CaptchaCode);

? ? Stream s = new MemoryStream(result.CaptchaByteData);

? ? return new FileStreamResult(s, "image/png");

}

現(xiàn)在,嘗試訪問這個Action,你應該能看到像這樣的驗證碼圖片:

3

使用驗證碼

在你需要提交內容到服務器端的model里加入一個新的屬性,叫做CaptchaCode

[Required]

[StringLength(4)]

public string CaptchaCode { get; set; }

在View中加入一個對應CaptchaCode的輸入框,以及一個調用GetCaptchaImage的圖片

<div class="input-group">

? ? <div class="input-group-prepend">

? ? ? ? <img id="img-captcha" data-src="~/get-captcha-image" />

? ? </div>

? ? <input type="text" class="form-control" placeholder="Captcha Code" asp-for="CaptchaCode" maxlength="4" />

? ? <span asp-validation-for="CaptchaCode" class="text-danger"></span>

</div>

在處理用戶提交數(shù)據的Action中加入檢查驗證碼的邏輯

if (ModelState.IsValid)

{

? ? // Validate Captcha Code

? ? if (!Captcha.ValidateCaptchaCode(model.CaptchaCode, HttpContext))

? ? {

? ? ? ? // return error

? ? }

? ? // continue business logic

}

4

再完善一點

你可以用jQuery實現(xiàn)用戶點擊圖片刷新驗證碼

$("#img-captcha").click(function () {

? ? resetCaptchaImage();

});


function resetCaptchaImage() {

? ? d = new Date();

? ? $("#img-captcha").attr("src", "/get-captcha-image?" + d.getTime());

}

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結

以上是生活随笔為你收集整理的ASP.NET Core 生成验证码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。