.NET Core API 产生 server-side 验证码

前言

因为正在开发的系统是内部类型,希望只是简单建立server-side的验证码机制就好,所以就不考虑使用Google reCaptcha。网路上.NET Core文章有点乱,版本又杂(微软根本版本之鬼...),顺手整理一下

环境

.NET 版本: .NET Core 5

后端

.NET Core的所有物件皆须已注入的方式使用,而我们这次要将验证码储存在Session 中。

需要先在startup.cs 中增加以下项目:

app.UseSession() ,告诉.NET Core需要使用Sessionservices.AddDistributedMemoryCache() ,注入分散式记忆体快取物件,Session会用到services.AddSession() ,注入Seesionservices.AddHttpContextAccessor() ,后面会说明为什么有这行。

startup.cs

public void ConfigureServices(IServiceCollection services){ // 注入分散式记忆体快取     services.AddDistributedMemoryCache(); // 注入Session services.AddSession(options => {       options.IdleTimeout = TimeSpan.FromMinutes(10);//You can set Time         });     // 注入 HttpContextAccessor     services.AddHttpContextAccessor();     services.AddControllers();     services.AddSwaggerGen(c =>     {        c.SwaggerDoc("v1", new OpenApiInfo { Title = "TestValidation", Version = "v1" });     });}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){  if (env.IsDevelopment())      {         app.UseDeveloperExceptionPage();         app.UseSwagger();         app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestValidation v1"));      }      app.UseHttpsRedirection();      app.UseRouting();  // 使用Session      app.UseSession();       app.UseAuthorization();      app.UseEndpoints(endpoints =>      {         endpoints.MapControllers();      });}

接下来我们建立一个.NET Core 类别库专案,并建立CodeValidation.csinterfaceclass 放在同一个档案,方便使用。

这里要注意一点,.NET Core很多东西是要自己额外安装:

IHttpContextAccessor需要从nuget安装套件: Microsoft.AspNetCore.Http
public interface ICodeValidator{        /// <summary>        /// 验证        /// </summary>        /// <param name="code"></param>        /// <returns></returns>        bool Validate(string code);        /// <summary>        /// 产生验证码        /// </summary>        /// <returns></returns>        string Generate();}public class CodeValidator : ICodeValidator{      private const string KEY = "ValidationCode";      private HttpContext _httpContext { get; set; }  // 注入 IHttpContextAccessor ,因为我们要使用HttpContext取得Session      public CodeValidator(IHttpContextAccessor httpContextAccessor)      {          _httpContext = httpContextAccessor.HttpContext;      }      public string Generate()      {          string code = CreateRandomWord(5);  // session只能储存byte[],将字串转为byte[]          byte[] codeBytes = Encoding.ASCII.GetBytes(code);          _httpContext.Session.Set(KEY, codeBytes);          return code;      }      public bool Validate(string code)      {          bool isOk = false;          byte[] codeBytes = null;          if(_httpContext.Session.TryGetValue(KEY,out codeBytes))        {  // 从Session取出来的byte[] 转成字串              string serverCode = Encoding.ASCII.GetString(codeBytes);  // 忽略大小写比对              if (serverCode.Equals(code, StringComparison.InvariantCultureIgnoreCase))              {                  isOk = true;              }          } // 无论成功失败,都清除Session。(依情境,非必要)         _httpContext.Session.Remove(KEY);         return isOk;     }     /// <summary>     /// 产生随机字串     /// </summary>     /// <param name="length"></param>     /// <returns></returns>     private string CreateRandomWord(int length = 5)     {            string code = "";            var letters = "ABCDEFGHJKMPQRSTUVWXYZ23456789abcdefghjkmpqrstuvwxyz".ToArray();            Random r = new Random();            for (int i = 0; i < length; i++)            {                int index = r.Next(0, letters.Length);                code += letters[index];            }            return code;     }}

这就是为什么我们会注入HttpContextAccessor 的原因,因为实际专案基本上都是分层架构,所以要在不同层级取得Session,就必须注入此物件,而不是从Controller传入HttpContext。

接下来我们需要将CodeValidator 注入给Controller使用,所以startup.cs 要增加程式

public void ConfigureServices(IServiceCollection services){ // 注入分散式记忆体快取     services.AddDistributedMemoryCache(); // 注入Session services.AddSession(options => {       options.IdleTimeout = TimeSpan.FromMinutes(10);//You can set Time         }); // 注入验证物件     services.AddScoped(typeof(ICodeValidator), typeof(CodeValidator));     // 注入 HttpContextAccessor     services.AddHttpContextAccessor();     services.AddControllers();     services.AddSwaggerGen(c =>     {        c.SwaggerDoc("v1", new OpenApiInfo { Title = "TestValidation", Version = "v1" });     });}

建立CodeController 製作验证码API。

[Route("api/[controller]")][ApiController]public class CodeController : ControllerBase{   private ICodeValidator _codeValidator { get; set; }   public CodeController(ICodeValidator codeValidator)   {      _codeValidator = codeValidator;   }   [HttpGet]   public ActionResult<string> Generate()   {      string code = _codeValidator.Generate();      return Ok(code);   }   [HttpGet("{code}")]   public ActionResult Validate(string code)   {      bool isOk = _codeValidator.Validate(code);      return isOk ? Ok() : BadRequest();   }}

测试结果

取得验证码,反回CDXPM

http://img2.58codes.com/2024/20138428F87AKxz1qY.png

输入验证码验证,返回200 OK

http://img2.58codes.com/2024/20138428ZDgDGBdSPn.png

输入错误测试

从新取得验证码 psBw9

http://img2.58codes.com/2024/20138428St1x7kldNk.png

输入错误的验证码12345,返回400 BadRequest

http://img2.58codes.com/2024/20138428na87hVQvFr.png

参考

https://www.notion.so/NET-Core-API-server-side-1addd16902de42649fca2e06cf99d60c#28bdfb0a137f42ed930ec2d7f41de5https://www.c-sharpcorner.com/article/how-to-use-session-in-asp-net-core/

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章