目录
[ASP.NET Core Identity 中的身份验证工作原理](#ASP.NET Core Identity 中的身份验证工作原理)
[在身份验证中更改默认登录 URL](#在身份验证中更改默认登录 URL)
[ASP.NET Core 身份验证](#ASP.NET Core 身份验证)
[ASP.NET Core Identity 登录页面](#ASP.NET Core Identity 登录页面)
[ASP.NET Core 身份注销](#ASP.NET Core 身份注销)
[ASP.NET Core 身份 Cookie](#ASP.NET Core 身份 Cookie)
[身份 Cookie 超时](#身份 Cookie 超时)
[ASP.NET Core Identity 记住我](#ASP.NET Core Identity 记住我)

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。
示例代码:https://download.csdn.net/download/hefeng_aspnet/92599900
ASP.NET Core 中的身份验证是什么?身份验证是指在用户成功登录应用程序时识别其身份的过程。ASP.NET Core Identity 会显示一个登录表单,用户需要在其中输入用户名和密码进行身份验证。登录成功后,Identity 会验证用户身份,并授予其访问 ASP.NET Core 应用程序安全资源的权限。
ASP.NET Core Identity 中的身份验证工作原理
让我们创建ASP.NET Core 身份验证 功能,该功能仅允许经过身份验证的用户访问控制器。首先,创建一个名为HomeController.cs的新控制器,并添加一个名为++Secured 的++ 操作方法,该方法向视图返回字符串消息" ++Hello "。++
using Microsoft.AspNetCore.Mvc;
namespace Identity.Controllers
{
public class HomeController : Controller
{
public IActionResult Secured()
{
return View((object)"Hello");
}
}
}
接下来,在Views ➤ Home文件夹中添加++Secured.cshtml++ Razor 视图,并添加以下代码:
@model string
@{
ViewData["Title"] = "Authentication";
}
<h1 class="bg-info text-white">Secured</h1>
@Model
该视图除了显示控制器返回的字符串"Hello"之外,没有其他特殊功能。现在运行项目,您将在浏览器中看到++"Hello"消息,请参见下图:++

这里不需要身份验证,所以我们可以不受任何限制地调用安全操作方法。运行应用程序时,浏览器向主控制器的安全操作方法发送了一个++未经身份验证的请求++ (匿名请求)。这个未经身份验证的请求能够访问应用程序资源,也就是主控制器,因此我们在浏览器上看到了"Hello"消息。
现在我们将通过应用身份验证来 ++限制++ 安全操作,以便用户必须先进行身份验证,然后身份验证系统才会授权他们调用操作方法。
请注意,身份授权与身份验证不同,它是在用户通过身份验证后才生效的。身份授权是指,只有在用户通过身份验证后,系统才会授权用户访问应用程序上的资源。
应用身份验证非常简单,只需在 Secured 操作方法上应用Microsoft.AspNetCore.Authorization命名空间的[Authorize]特性即可。这将限制只有经过身份验证的用户才能访问该方法。
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Identity.Controllers
{
public class HomeController : Controller
{
[Authorize]
public IActionResult Secured()
{
return View((object)"Hello");
}
}
}
现在再次运行该应用程序,这次我们会看到一条消息,提示"找不到本地主机页面。HTTP 错误 404"。如下图所示:

这里发生了两件事:
- 我们将[Authorize]属性应用于安全操作,因此现在用户必须先进行身份验证才能访问它。
- ASP.NET Core Identity 将我们重定向到++Account 控制器的 Login 操作++ ,这是 Identity 的默认登录 URL,其值为http://localhost:7263/Account/Login?ReturnUrl=%2F。在此页面,我们可以登录应用程序。稍后我们将构建此页面。
请注意,URL 包含名为++ReturnUrl 的++ 查询字符串变量,其中包含++%2F++ 。%2F是经过编码的 URL,代表++/++ 。因此,身份验证后,用户将被重定向到应用程序的主页 URL,即http://localhost:7263。
返回的 URL 将包含用户在身份验证之前尝试访问的安全页面 URL。身份验证成功后,身份系统会将用户重定向回该原始页面。
在身份验证中更改默认登录 URL
ASP.NET Core Identity 的默认登录 URL 为/Account/Login ,用户将被++重定向++ 到此处进行身份验证。此处会显示一个登录表单,供用户在 Identity 中完成登录流程。如果要更改此登录 URL,请转到++Program 类++并添加以下代码:
builder.Services.ConfigureApplicationCookie(opts => opts.LoginPath = "/Authenticate/Login");
这里我们将新的登录 URL 指定为/Authenticate/Login,即++https://localhost:7263/Authenticate/Login++ 。您的端口可能有所不同。请注意,此 URL 不能基于应用程序中的路由自动生成,因此,如果更改路由,则必须手动更改此处的++身份登录 URL++。
ASP.NET Core 身份验证
为了实现**身份验证,**我们需要创建两个页面------登录页面和注销页面。在登录页面,用户需要输入用户名和密码进行身份验证;在注销页面,用户可以点击注销按钮,即可从身份验证系统中注销。
ASP.NET Core Identity 登录页面
在Models文件夹内创建一个名为Login.cs 的类。该类包含三个属性:++Email、Password 和 ReturnUrl++,用于存储用户的登录信息。
由于用户登录时必须输入电子邮件和密码,因此这两个属性被设置为必填字段。ReturnUrl 属性将包含返回URL。
++Login.cs++类的代码如下:
using System.ComponentModel.DataAnnotations;
namespace Identity.Models
{
public class Login
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
public string ReturnUrl { get; set; }
}
}
Identity 的默认登录 URL 为++https://localhost:7263/Account/Login++ 。因此,我们需要创建++Account 控制器++ ,它将作为Identity 的登录控制器 。我们还将添加++Login 操作++方法,该方法将在用户执行登录操作时触发。
因此,请在++Controllers文件夹中创建++ AccountController.cs类,并添加以下代码:
using Identity.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace Identity.Controllers
{
Authorize
public class AccountController : Controller
{
private UserManager<AppUser> userManager;
private SignInManager<AppUser> signInManager;
public AccountController(UserManager<AppUser> userMgr, SignInManager<AppUser> signinMgr)
{
userManager = userMgr;
signInManager = signinMgr;
}
AllowAnonymous
public IActionResult Login(string returnUrl)
{
Login login = new Login();
login.ReturnUrl = returnUrl;
return View(login);
}
HttpPost
AllowAnonymous
ValidateAntiForgeryToken
public async Task<IActionResult> Login(Login login)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.FindByEmailAsync(login.Email);
if (appUser != null)
{
await signInManager.SignOutAsync();
Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
if (result.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
}
ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
}
return View(login);
}
}
}
代码说明
控制器类应用了[Authorize]特性,以防止++未经身份验证的++ 请求调用它。但是,我们为登录操作方法添加了[AllowAnonymous]特性,允许++未经身份验证的++请求调用这些操作方法。
请注意,必须允许未经身份验证的用户查看登录页面,否则他永远无法登录身份系统。
我们在控制器构造函数中添加了UserManager<AppUser>和SignInManager<AppUser>的依赖项,以便这些对象将由ASP.NET Core 的依赖注入功能提供。
相关代码如下:
private UserManager<AppUser> userManager;
private SignInManager<AppUser> signInManager;
public AccountController(UserManager<AppUser> userMgr, SignInManager<AppUser> signinMgr)
{
userManager = userMgr;
signInManager = signinMgr;
}
UserManager用于管理身份系统中的用户,而 SignInManager用于执行身份验证过程。
接下来,我们添加了登录操作方法的 HTTP GET 版本。我们为其应用了[AllowAnonymous]特性,使其无需身份验证。这一点显而易见,否则用户将无法登录。
此操作的参数中包含一个returnUrl变量,其值由ReturnUrl查询字符串变量提供。在后台,模型绑定会自动将返回 URL 值绑定到此变量。
操作方法代码为:
AllowAnonymous
public IActionResult Login(string returnUrl)
{
Login login = new Login();
login.ReturnUrl = returnUrl;
return View(login);
}
该操作会将++Login 类对象++ 作为模型返回给视图。请注意,我们将ReturnUrl属性的值设置为传递给该操作参数的值。
接下来,我们添加了登录操作方法的 POST 版本,用于执行用户的实际身份验证。该操作方法的代码如下:
HttpPost
AllowAnonymous
ValidateAntiForgeryToken
public async Task<IActionResult> Login(Login login)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.FindByEmailAsync(login.Email);
if (appUser != null)
{
await signInManager.SignOutAsync();
Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
if (result.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
}
ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
}
return View(login);
}
此操作方法有一个类型为Login.cs的参数,它通过该参数接收用户在Login.cshtml提供的登录表单中填写的登录值(即电子邮件和密码) 。该方法提供两个属性:
-
AllowAnonymous\]属性允许未经身份验证的请求调用它。
首先,我们从UserManager类的FindByEmailAsync()方法中获取用户详细信息。此方法接收用户在登录表单中提供的电子邮件地址。请参见以下代码:
AppUser appUser = await userManager.FindByEmailAsync(login.Email);
接下来,我们检查AppUser对象中接收到的用户详细信息是否不为空。如果为空,我们首先会注销所有已登录的用户:
await signInManager.SignOutAsync();
然后我们使用SignInManager类的PasswordSignInAsync方法将用户登录到应用程序。
Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
我们为最后第三个和第四个参数都提供了错误的值,因为我们既不希望持久登录使用持久 cookie(即使关闭浏览器后仍然存在),也不希望在登录失败时锁定用户帐户。
此方法返回SignInResult对象,其中包含登录过程的结果。如果登录成功,则其Succeeded属性包含true值,否则包含false 值。
最后,我们检查 ` Succeeded` 属性的值是否为真。如果是真,则将用户返回到返回 URL 的值。实现此功能的代码如下:
if (result.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
我们还需要登录视图,其中包含登录表单。此视图将构成身份登录页面,用户将在此执行帐户登录流程。因此,请在Views/Account文件夹中创建Login.cshtml Razor 视图文件,并添加如下所示的代码:
@model Login
@{
ViewData["Title"] = "Login";
}
<h1 class="bg-info text-white">Login</h1>
<div class="text-danger" asp-validation-summary="All"></div>
<form asp-action="Login" method="post">
<input type="hidden" asp-for="ReturnUrl" />
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
</div>
<button class="btn btn-primary" type="submit">Log In</button>
</form>
是时候测试身份验证功能了。我们已经注册了一个用户,其详细信息如下:
-
姓名 -- tom
-
邮箱 -- tom@yahoo.com
-
密码 -- Coder77@
现在我们将使用该用户的凭据登录。
如果您没有任何用户,请从 URL 创建一个新用户 -- https://localhost:7263/Admin/Create。
运行项目并访问"安全"链接(网址:https://localhost:7236/Home/Secured)。您将被重定向到登录页面。在此输入错误的登录凭据:
-
邮箱:tom@yahoo.com
-
密码:wrongpass
点击"登录"按钮后,我们会看到"登录失败:邮箱或密码无效"的提示信息。这是因为我们输入了错误的密码,请参见下图:

现在输入++正确的密码++ ,然后点击"登录"按钮。这次验证成功,您将被重定向到安全页面,页面上会显示"Hello"消息。请查看下图。

显示已登录用户的姓名
我们可以通过UserManager类的GetUserAsync()方法获取 Identity 中的当前用户。然后,我们可以在视图中显示当前用户名。请查看以下代码,了解如何获取已登录用户的姓名。
AppUser user = await userManager.GetUserAsync(HttpContext.User);
编辑Home Controller 的代码,获取用户并将其姓名发送到视图。
using Identity.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace Identity.Controllers
{
public class HomeController : Controller
{
private UserManager<AppUser> userManager;
public HomeController(UserManager<AppUser> userMgr)
{
userManager = userMgr;
}
Authorize
public async Task<IActionResult> Secured()
{
AppUser user = await userManager.GetUserAsync(HttpContext.User);
string message = "Hello " + user.UserName;
return View((object)message);
}
}
}
现在,用户登录后,其姓名将显示在浏览器上。
ASP.NET Core 身份注销
注销功能会将已登录用户从身份管理界面注销。因此,请在AccountController.cs文件中添加以下代码来实现注销操作方法:
public async Task<IActionResult> Logout()
{
await signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}
注销操作相当简单,它只是使用signInManager.SignOutAsync()将任何已登录用户从应用程序中注销。
应该使用锚点标签将注销操作方法链接到Secured.cshtml Razor 视图文件中。因此,请按如下所示更新此视图:
@model string
@{
ViewData["Title"] = "Authentication";
}
<h1 class="bg-info text-white">Index</h1>
@Model
@if (User?.Identity?.IsAuthenticated ?? false)
{
<a asp-controller="Account" asp-action="Logout" class="btn btn-danger">Logout</a>
}
这里我们使用了Microsoft.AspNetCore.Mvc.Razor命名空间中的RazorPageBase类。该类的User.Identity.IsAuthenticated属性在用户登录时返回 true,否则返回null。我们利用这一点,仅在用户登录应用程序时才显示"注销"链接。
运行应用并使用用户帐户登录。登录后,您将被重定向到主页,在那里可以看到"注销"按钮。单击该按钮即可从 ASP.NET Core Identity 注销。请参见下图:

ASP.NET Core 身份 Cookie
ASP.NET Core Identity 使用++Cookie++ 来确定用户当前是否++已通过身份验证++ 。此 Cookie 在用户通过身份验证后创建并存储在浏览器中。每次发出++HTTP 请求++时(例如,当我们在浏览器中打开应用程序的任何 URL 时),都会将相同的 Cookie 发送到服务器。这使得 Identity 能够确定请求来自哪个用户。
此 Cookie 名称为++.AspNetCore.Identity.Application 。我们可以在 Chrome 浏览器开发者工具的++ "应用程序"选项卡中查看此 Cookie 。请参见下图:

注意 -- 要从 Identity 中注销任何用户,只需选择此 cookie 并单击"X"符号即可删除此 cookie。
身份 Cookie 超时
我们可以使用++IServiceCollection++ 接口的ConfigureApplicationCookie方法设置ASP.NET Core Identity Cookie 的++过期时间++。
我们在 Program 类中使用以下代码,以滑动过期方式将过期时间设置为 20 分钟。
builder.Services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = ".AspNetCore.Identity.Application";
options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
options.SlidingExpiration = true;
});
ASP.NET Core Identity 记住我
我们将创建**"记住我"**功能,确保 Identity 能够长时间记住我们。我们只需首次登录,Identity 就会在浏览器中为我们创建一个持久性 cookie。

为了实现这个功能,我们需要在登录页面添加一个"记住我"复选框。
@model Login
@{
ViewData["Title"] = "Login";
}
<h1 class="bg-info text-white">Login</h1>
<div class="text-danger" asp-validation-summary="All"></div>
<form asp-action="Login" method="post">
<input type="hidden" asp-for="ReturnUrl" />
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
</div>
<div class="form-group">
Remember me? <input type="checkbox" asp-for="Remember" />
</div>
<button class="btn btn-primary" type="submit">Log In</button>
</form>
现在在 Login.cs 类中添加一个名为 Remember 的布尔类型属性,如下所示。
public class Login
{
Required
public string Email { get; set; }
Required
public string Password { get; set; }
public string ReturnUrl { get; set; }
public bool Remember { get; set; }
}
该属性将通过模型绑定技术自动绑定到"记住我"复选框的值。
现在我们可以将此属性值分配给"PasswordSignInAsync"方法的第三个参数,如下所示。
HttpPost
AllowAnonymous
ValidateAntiForgeryToken
public async Task<IActionResult> Login(Login login)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.FindByEmailAsync(login.Email);
if (appUser != null)
{
await signInManager.SignOutAsync();
Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, login.Remember, false);
if (result.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
}
ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
}
return View(login);
}
启用此功能后,用户可以选择勾选"记住我"复选框,从此无需再次登录。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。