ASP.NET Core - 身份验证 UI 安装
本教程介绍如何使用 `Microsoft.AspNetCore.Identity.UI` 包为现有的 ASP.NET Core 项目添加身份验证功能。
引言
在本文中,我想向您展示如何使用 Microsoft.AspNetCore.Identity.UI
NuGet 包为现有的 ASP.NET Core 项目添加身份验证功能。该程序包可以极大地帮助我们,但我们需要了解该程序包的内容以及如何将其集成到我们的应用程序中。
在本教程中,从 ASP.NET Core Web 应用程序模板开始,您将看到身份验证 UI 和身份持久化如何轻松地安装到现有的 Web 应用程序中。您的 Web 应用程序将具有以下功能:
- 注册新用户
- 更改用户密码
- 登录应用程序
- 退出应用程序
要求
- .NET Core SDK 2.1 (2.1.403)
- PostgreSQL 10.3
本文内容也已在 .NET Core 2.1.302 版本上得到验证。
PostgreSQL 将用作身份持久化的存储。
安装步骤
- 身份验证和身份 UI 配置
- 身份持久化实现
- 页面过渡实现
1. 身份验证和身份 UI 配置
使用 ASP.NET Core Web App 模板创建项目并运行它。您可以看到模板生成的网页。如您所见,没有“登录”或“注册”链接。
在进行下一步之前,让我们将 `Microsoft.AspNetCore.App` 包更新到最新版本。在本例中,生成的项目是 2.1.1 版本,我将其更新为 2.1.5。
更新包后,您可能会收到一个生成错误 NETSDK1061。不用担心,这并不严重。您只需要稍微编辑一下 csproj 文件。如果您的项目文件中有如下所示的行,那么这就是原因。
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
将 `Version` 属性添加到节点,如下所示,错误将消失。
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.5" />
</ItemGroup>
如果您使用的是 Visual Studio 2017,您将在 NuGet 包树的 `Microsoft.AspNetCore.App` 包下看到以下两个包。这些是我们即将使用的包。
Microsoft.AspNetCore.Authentication
Microsoft.AspNetCore.Identity.UI
为了集成这些包,您需要配置您的 Web 应用程序。这些包提供了扩展方法,我们可以轻松地完成配置。
将以下代码添加到 `Startup.cs` 中的 `Configure` 方法中
app.UseAuthentication();
以及 `ConfigureServices` 方法中的以下代码。
services.AddDefaultIdentity<IdentityUser>();
现在,您的 Web 应用程序已配置为将以下 URL 的请求路由到 `Identity` UI 包中的代码。
- /Identity/Account/Register
- /Identity/Account/Login
- /Identity/Account/Manage
- /Identity/Account/Logout
但是,这些仍然不起作用,因为这些视图需要一个部分视图,该视图位于 `/Views/Shared/` 目录下,名为 `_LoginPartial.cshtml`。
创建部分视图文件。您不必在其中包含任何内容,因此现在将其保留为空文件。
2. 身份持久化实现
在您看到上述 URL 的内容之前,您需要完成身份持久化的实现。包中的代码需要一个存储来持久化身份验证信息。
首先,有一个数据库,其次,将您的应用程序配置为使用 Entity Framework Core。然后,您可以使用 Entity Framework Core 工具生成所需的表。
创建数据库
如果您已经有一个可以用于此目的的数据库,请跳过本节。如果没有,请按照以下说明在本地计算机上快速创建一个空的 PostgreSQL 数据库。
如果您还没有 PostgreSQL 服务器,请安装它,并在任意位置为您的数据库创建一个新目录,同时授予服务器进程用户的访问权限。之后,创建一个带有以下 SQL 脚本的文本文件,并将其命名为 `CreateDb.sql`。
create role :name with LOGIN PASSWORD :pw;
create tablespace :name location :dir;
set default_tablespace = :name;
create database :name owner :name encoding 'UTF-8' template template0;
然后,在 `psql` 中使用以下命令运行它,同时将 `$DB_DIR` 替换为您刚刚创建的数据库目录路径。该脚本创建一个数据库用户和一个新数据库,两者名称相同,均为 `sampledb`。
psql -U postgres -f CreateDb.sql -v dir="'$DB_DIR'" -v name=sampledb -v pw="'sample'"
如果您以后想删除并重新创建数据库,请使用以下脚本和命令。
\c postgres
drop database if exists :name;
drop tablespace if exists :name;
drop role if exists :name;
psql -U postgres -f DeleteDb.sql -v name=sampledb
您无需再次删除并创建数据库目录。运行它之后,再次运行数据库创建脚本。
为 Entity Framework Core 配置 ASP.NET Core
现在,已经有一个数据库准备好连接了。让我们配置 ASP.NET Core 以通过 Entity Framework Core 连接到数据库。以下说明假定您使用的是 PostgreSQL 数据库。
首先,为身份验证信息创建一个数据库上下文类。您可以直接使用 `Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext`,但这仅在您的应用程序中仅为 `IdentityDbContext` 而使用 Entity Framework 时才可能。
namespace IdentityUiSample.Models
{
public class AppIdentityDbContext : IdentityDbContext
{
public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options) { }
}
}
接下来,添加以下两个 NuGet 包,并将以下行添加到 `Startup.ConfigureServices` 方法中。
Npgsql.EntityFrameworkCore.PostgreSQL
Npgsql.EntityFrameworkCore.PostgreSQL.Design
services.AddDbContext<AppIdentityDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("SampleDB")));
然后,将 `SampleDB` 连接字符串添加到 `appsettings.json` 中,如下所示:
{
"ConnectionStrings": {
"SampleDB": "Server=localhost;Database=sampledb;User Id=sampledb;Password=sample;"
}
}
最后,在您之前添加的代码之后,调用 `AddEntityFrameworkStores` 方法并使用 `AppIdentityDbContext` 类。
services
.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<AppIdentityDbContext>();
使用 Entity Framework Core 工具创建表
现在,您已经有了数据库和使用 Entity Framework Core 的代码。您终于可以使用 Entity Framework Core 工具来生成数据库表了。
在项目根目录下,按顺序运行以下两个命令。在运行这些命令之前,请确保您的 Web 应用程序未运行。否则,这些工具将失败。这是因为工具需要运行您的应用程序。
这两个命令中命令行开关 `-c` 的值是您的数据库上下文的完整名称。请替换该名称以匹配您的数据库上下文类型。如果您的应用程序只有一个数据库上下文,则可以省略该开关。
dotnet ef migrations add first -c IdentityUiSample.Models.AppIdentityDbContext -v
dotnet ef database update -c IdentityUiSample.Models.AppIdentityDbContext -v
这些命令成功后,您将在项目根目录下找到一系列新表和 `Migrations` 目录,其中包含生成的 P文件。
当您对数据库上下文类进行一些更改并需要再次运行这些工具时,请再次运行这两个命令,但将第一个命令中的 `first` 更改为任何其他关键字。
好的,现在您应该可以看到登录页面了。运行 Web 应用程序,然后在浏览器中导航到路径 `/Identity/Account/Register`。尝试注册一个帐户,然后使用该帐户登录 `/Identity/Account/Login`。
3. 页面过渡实现
您可能已经注意到,您的应用程序中没有任何登录链接。因此,最后一部分将添加页面过渡,以便将身份验证功能集成到您的应用程序中。
您创建的部分视图 `_LoginPartial.cshtml` 渲染在导航栏中,因此是添加与身份验证相关的页面的链接的好地方。以前,您将其创建为空文件。现在,在其中国添加以下代码。
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
@model dynamic
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="nav navbar-nav navbar-right">
@if (SignInManager.IsSignedIn(User))
{
<li><a href="/Identity/Account/Manage">@UserManager.GetUserName(User)</a></li>
<li>
<form asp-area="Identity" asp-page="/Account/Logout" method="post">
@Html.Hidden("returnUrl", "/")
<input type="submit" value="Logout" class="btn btn-link navbar-btn navbar-link" />
</form>
</li>
}
else
{
RegisterModel register = Model as RegisterModel;
LoginModel login = Model as LoginModel;
@if (register == null)
{
<li><a href="/Identity/Account/Register">Register</a></li>
}
@if (login == null)
{
<li><a href="/Identity/Account/Login">Login</a></li>
}
}
</ul>
在 Razor 视图中获取用户信息
以 `@inject` 指令开头的行允许您在 Razor 视图代码中引入登录信息。然后,您可以通过 `@UserManager.GetUserName(User)` 获取当前登录用户的用户名。
_LoginPartial.cshtml 的模型
之所以通过 `@model dynamic` 将模型接收为动态,是因为部分视图不仅在登录页面上渲染,还在其他页面上渲染,并且在每个页面上都会传递不同的模型类型。通过将模型定义为动态,视图可以在任何情况下接收模型实例。
注销链接
到 `/Identity/Account/Logout` 的链接被编码为带有 `asp-area` 和 `asp-page` 属性的表单。这是因为需要带有防伪标记的 `POST` 请求。使用 `asp-` 属性不是必需的,只是使代码稍微简单一些。以下代码是等效的,其中您可以看到防伪标记的代码。
<form action="/Identity/Account/Logout" method="post">
@Html.AntiForgeryToken()
@Html.Hidden("returnUrl", "/")
<input type="submit" value="Logout"
class="btn btn-link navbar-btn navbar-link" />
</form>
顺便说一句,表单数据 `returnUrl` 是可选的。它只是允许跳过 `Logout` 页面并重定向到某个路径。
将部分视图安装到 _Layout.cshtml
最后,转到 `/Views/Shared/_Layout.cshtml`,这是您的应用程序默认使用的布局。搜索“`navbar-nav`”并找到如下所示的行,然后添加用斜体显示的这一行。
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home"
asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home"
asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home"
asp-action="Contact">Contact</a></li>
</ul>
<partial name="~/Views/Shared/_LoginPartial.cshtml" />
</div>
完成了!
现在,尝试登录和注销。从用户名的链接,您可以转到帐户管理页面。
后续步骤
`Identity` UI 中的某些功能尚未完全配置。例如,`ForgotPassword` 页面实际上并未发送电子邮件。有关进一步的配置,请参阅Microsoft 网站上的说明。我相信,在您完成本教程之后,阅读那里的说明并不困难。
示例
您可以从上面的链接获取本教程的示例项目。但是,请注意,为了运行它,您仍然需要自己实现身份持久化。
历史
- 2018-11-10:发布第一个编辑