ASP.NET Core Authentication系列(二)實(shí)現(xiàn)認(rèn)證、登錄和注銷
前言
在上一篇文章介紹ASP.NET Core Authentication的三個(gè)重要概念,分別是Claim, ClaimsIdentity, ClaimsPrincipal,以及claims-base authentication是怎么工作的。
這篇文章來介紹一下如何基于claims-base authentication來實(shí)現(xiàn)認(rèn)證、登錄和注銷功能的。源代碼從這里下載。
認(rèn)證是一個(gè)確定發(fā)送請(qǐng)求的訪問者身份的過程,與認(rèn)證相關(guān)的還有另外兩個(gè)基本操作:登錄和注銷。
ASP.NET Core應(yīng)用的認(rèn)證實(shí)現(xiàn)在一個(gè)名為AuthenticationMiddleware的中間件中,該中間件在處理分發(fā)給它的請(qǐng)求時(shí)會(huì)按照指定的?認(rèn)證方案(Authentication Scheme)?從請(qǐng)求中提取能夠驗(yàn)證用戶真實(shí)身份的數(shù)據(jù),我們一般將該數(shù)據(jù)稱為?安全令牌(Security Token)?。
ASP.NET Core應(yīng)用下的安全令牌被稱為?認(rèn)證票據(jù)(Authentication Ticket)?,所以ASP.NET Core應(yīng)用采用基于票據(jù)的認(rèn)證方式。
AuthenticationMiddleware中間件的整個(gè)認(rèn)證過程涉及下圖的三種操作:認(rèn)證票據(jù)的頒發(fā)、檢驗(yàn)和撤銷。

ASP.NET Core應(yīng)用的認(rèn)證系統(tǒng)旨在構(gòu)建一個(gè)標(biāo)準(zhǔn)的模型來完成針對(duì)請(qǐng)求的認(rèn)證以及與之相關(guān)的登錄和注銷操作。接下來我們就通過一個(gè)簡(jiǎn)單的實(shí)例來演示如何在一個(gè)ASP.NET Core應(yīng)用中實(shí)現(xiàn)認(rèn)證、登錄和注銷的功能。
大多數(shù)Web應(yīng)用采用的是Cookie來保存認(rèn)證票據(jù),因此我們采用基于Cookie的認(rèn)證方案。
配置
在Startup.ConfigureServices方法里,添加AuthenticationMiddleware中間件:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
然后在Startup.Configure方法里,調(diào)用UseAuthentication和UseAuthorization來設(shè)置HttpContext.User屬性以及允許請(qǐng)求經(jīng)過AuthenticationMiddleware,并且要在UseEndpoints之前調(diào)用:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){????//?...????app.UseAuthentication();????app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");????});????????// ...}
登錄
接下來實(shí)現(xiàn)登錄方法,常見是使用“用戶名+密碼”,這里使用一個(gè)靜態(tài)字典來模擬用戶表。
public class AccountController : Controller{????//?....????private?static?Dictionary<string,?string>?_accounts;static AccountController(){_accounts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);_accounts.Add("Foo", "password");_accounts.Add("Bar", "password");_accounts.Add("Baz", "password");}[]public IActionResult Login(){????????LoginModel?model?=?new?LoginModel();return View(model);}[]public async Task<IActionResult> Login(LoginModel model){if (_accounts.TryGetValue(model.UserName, out var pwd) && pwd == model.Password){var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, model.UserName) }, "Basic");var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);return Redirect("/");}else{????????????model.ErrorMessage?=?"Invalid?user?name?or?password!";return await Task.Run(() => View(model));}????}// ....}
這段代碼的關(guān)鍵在于下面三行代碼:
創(chuàng)建ClaimType為Name,值為用戶名的Claim。
創(chuàng)建ClaimsIdentity,注意AuthorizeType="Basic"。
創(chuàng)建ClaimsPrincipal。
調(diào)用HttpContext.SignInAsync登錄,其中認(rèn)證方案為CookieAuthenticationDefaults.AuthenticationScheme,與配置時(shí)一致。
var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, model.UserName) }, "Basic");var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
認(rèn)證
需要授權(quán)訪問的功能要驗(yàn)證登錄狀態(tài),如果沒有登錄則不允許訪問,使用方法很簡(jiǎn)單,只需要在Action上加上特性[Authorize]:
[]public IActionResult Index(){return View();}
未登錄會(huì)跳轉(zhuǎn)到/Account/Login(默認(rèn)設(shè)置,可修改),避免未授權(quán)訪問。
注銷
用戶注釋,即將具有認(rèn)證票據(jù)的Cookie設(shè)置為過期,直接調(diào)用HttpContext.SignOutAsync,注意認(rèn)證方案要與配置和登錄的一致:CookieAuthenticationDefaults.AuthenticationScheme
參考資料public class AccountController : Controller{????//?....public async Task<IActionResult> Logout(){_logger.LogInformation("User {Name} logged out at {Time}.",????????????????User.Identity.Name,?DateTime.UtcNow);????????await?HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);return Redirect("/");????}????// ....}
Exploring the cookie authentication middleware in ASP.NET Core
用最簡(jiǎn)單的方式在ASP.NET Core應(yīng)用中實(shí)現(xiàn)認(rèn)證、登錄和注銷
Use cookie authentication without ASP.NET Core Identity

