大家好,我是張飛洪,感謝您的閱讀,我會不定期和你分享學習心得,希望我的文章能成為你成長路上的墊腳石,讓我們一起精進。
在本章,我們將學習如何客製化ASP.NET Core認證機制。微軟把安全認證當做ASP.NET Core框架的一部分,足以看見它是應用程式非常最重要的內容。在文將介紹如何客製化ASP.NET Core認證UI的基本實現,以及如何向IdentityUser新增自定義資訊。我們將介紹以下幾點:
建立一個ASP.NET Core應用程式並用VS Code開啟:
dotnet new mvc -n AuthSample -o AuthSample --auth Individual
cd AuthSample
code .
使用者身份是表示使用者物件,也可以是使用者組。通過它我們可以瞭解使用者及其所屬的許可權。可以給身份或者叫使用者分配包含許可權的角色。例如,可以給一個名為倉庫管理員的角色只分配寫入的許可權。使用者身份也可以巢狀。一個使用者可以是一個組的一部分,一個組可以是另一個組的一部分,依此類推。
ASP.NET Core Identity是一個框架,它在.NET中用來儲存和讀取使用者資訊。該框架還提供了新增登入表單、登入檔單、對談處理等機制。它還提供以加密和安全的方式儲存憑據。ASP.NET Core Identity還提供了多種驗證使用者身份的方法:
上面命令列裡的--auth標誌設定為Individual,用於啟用個人身份驗證,並建立ASP.NET Core MVC應用程式。這意味著它附帶了一個資料庫來儲存使用者。--auth標誌會新增所有相關的程式碼和依賴項。
--auth標誌建立了一個名為Identity的區域,其中包含_ViewStart.cshtml檔案,它參照新專案的_Layout.cshtml檔案。實際的登入或註冊介面在參照此專案的類庫中提供。
該案例專案包含一個Data資料夾,其中包含EF Core的DbContext,以及用於建立和更新的資料庫遷移。
除了Program.cs外,所有其他部分常規MVC應用完全相同。
如果您使用.NET CLI建立了應用程式,預設則會使用SQLite資料庫。如果使用Visual Studio建立此應用程式,則會使用SQL Server儲存使用者資料。
在啟動應用程式之前,在終端中呼叫以下命令建立和更新資料庫:
dotnet ef database update
如果不起作用,您可能需要首先在.NET CLI中安裝實體框架工具:
dotnet tool install -g dotnet-ef
然後執行:
dotnet watch
應用程式現在將在監視模式下啟動,並啟用熱重新載入。它還將開啟瀏覽器視窗並呼叫應用程式:
如您所見,右上方有一個選單,其中包含此應用程式的「註冊」和「登入」選項。單擊登入連結可進入以下登入螢幕:
如上所述,該檢視來自一個已編譯的Razor庫,它為Identity區域提供了必要的檢視。我們會自動從框架中獲取此UI。
最後,我們快速瞭解一下Program.cs,這也與我們在上一章中看到的檔案不同。
在註冊服務的上部,有幾行程式碼用於註冊DbContext以及資料庫異常頁:
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
還有新增身份認證的EntityFramework Core的註冊。它被設定為只允許確認的帳戶,這意味著:作為使用者需要確認電子郵件才能登入。
在中介軟體的下部,我們看到使用了身份驗證和授權:
app.UseAuthentication();
app.UseAuthorization();
身份驗證通過讀取身份驗證cookie來識別使用者,它還將所有相關資訊新增到Identity物件。
我們可能還需要通過向用戶新增更多屬性來擴充套件使用者組態檔。我們在下面介紹如何做到這一點。
IdentityUser具有以下欄位:Id、使用者名稱、密碼、電子郵件和電話號碼。
由於顯示名稱可能與使用者名稱不同,我們會新增Name屬性,另外,假設我們想向用戶傳送生日祝福,我們應該如何擴充套件他們的出生日期呢?
為此,需要新增一個名為WebAppUser.cs的檔案到Data資料夾中:
using Microsoft.AspNetCore.Identity;
namespace AuthSample.Data;
public class WebAppUser : IdentityUser {
[PersonalData]
public string? Name { get; set; }
[PersonalData]
public DateTime DOB { get; set; }
}
如上所示,WebAppUser.cs派生自IdentityUser,並擴充套件兩個屬性。
在Program.cs,我們需要修改服務註冊以使用新的WebAppUser:
builder.Services.AddDefaultIdentity<WebAppUser>
我們還需要更改DbContext,使用WebAppUser:
public class ApplicationDbContext : IdentityDbContext<WebAppUser, IdentityRole, string>
您還需要將using語句新增到Microsoft.AspNetCore.Identity中。這是第一步。我們現在需要更新資料庫:
dotnet ef migrations add CustomUserData
dotnet ef database update
一旦使用自定義屬性擴充套件了IdentityUser,就可以在在ASP.NET Core Identity U的使用者組態檔中使用它。
ASP.NET Core Identity檢視來自編譯的Razor庫,我們應該如何自定義呢?
我們只需要在Area內的預定義資料夾結構中用自定義檢視覆蓋給定檢視即可。前提是我們需要先建立一個自定義檢視,新增擴充套件欄位或更改佈局。
如前所述,專案中已經有一個名為Identity的Area,內有一個Pages資料夾。在這裡,我們需要建立一個名為Account的新資料夾,然後放置一個名為「註冊」的新Register.cshtml頁面在這個資料夾中,並將以下內容放在裡面,以檢視檢視的覆蓋是否有效:
@page @{ } <h1>Hello Register Form</h1>
執行應用程式並單擊左上角的註冊,您將看到以下頁面:
實際上,我們不需要自己覆蓋檢視。有一個程式碼生成器可用於構建您想要覆蓋的檢視。
通過呼叫以下命令安裝程式碼生成器:
dotnet tool install -g dotnet-aspnet-codegenerator
如果尚未完成,您還需要在專案中安裝以下軟體包:
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
要了解程式碼生成器可以做什麼,請執行以下命令:
dotnet aspnet-codegenerator identity -h
第一個更改是讓使用者在註冊頁面上填寫name屬性,我們先構建註冊頁面:
dotnet aspnet-codegenerator identity -dc AuthSample.Data.ApplicationDbContext --files "Account.Register" -sqlite
此命令告訴程式碼生成器使用現有的ApplicationDbContext和Sqlite。如果不指定此項,它將建立一個新的DbContext或註冊現有的DbContext,以便與SQLServer而不是SQLite一起使用。
如果一切都OK了,程式碼生成器應該只新增Register.cshtml頁面以及一些基礎結構檔案:
程式碼生成器還會知道專案正在使用自定義WebAppUser而不是IdentityUser,這意味著在生成的程式碼中使用了WebAppUser。
現在,我們更改一下Register.cshtml,將顯示名稱新增到表單中。在第15行電子郵件欄位的表單元素之前新增以下行:
<div class="form-floating">
<input asp-for="Input.Name" class="form-control" autocomplete="name" aria-required="true" />
<label asp-for="Input.Name"></label>
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
此外,Regiser.cshtml.cs需要更改。ImportModel類需要Name屬性:
public class InputModel {
[Required]
[Display(Name = "Display name")]
public string Name { get; set; }
在PostAsync方法中,將Name屬性分配給新建立的使用者:
var user = CreateUser();
user.Name = Input.Name;
啟動申請後,您將看到以下登入檔格:
由於使用者可能需要更新名稱,我們還需要更改組態檔頁面上的檢視。這裡還需要新增出生日期:
dotnet aspnet-codegenerator identity -dc AuthSample.Data.ApplicationDbContext --files "Account.Manage.Index" -sqlite
開啟新建立的Index.chtml.cs,並將以下屬性放在InputModel類中:
public class InputModel {
[Required]
[Display(Name = "Display name")]
public string Name { get; set; }
[Display(Name = "Date of birth")]
public DateTime DOB { get; set; }
}
現在可以在相應的Index.chtml中使用這些屬性。下面程式碼片段需要放在驗證和使用者名稱之間:
<div class="form-floating">
<input asp-for="Input.Name" class="form-control" autocomplete="name" aria-required="true" />
<label asp-for="Input.Name"></label>
<span asp-validation-for="Input.Name" class="text-danger">
</span>
</div>
<div class="form-floating">
<input asp-for="Input.DOB" class="form-control" type="date"/>
<label asp-for="Input.DOB" class="form-label"></label>
</div>
最後,還需要一些更改才能用儲存的資料填充表單。在LoadAsync方法中,需要使用新屬性擴充套件InputModel的範例化:
Input = new InputModel {
PhoneNumber = phoneNumber,
Name = user.Name,
DOB = user.DOB
};
使用者儲存表單時,還需要儲存更改的值。將下一個程式碼段放在OnPostAsync方法中:
user.Name = Input.Name;
user.DOB = Input.DOB;
await _userManager.UpdateAsync(user);
將InputModel的值設定為WebAppUser屬性,並將更改儲存在資料庫中。
我們在終端中呼叫dotnet watch來嘗試一下。
Profile頁面現在看起來類似於:
您現在可以更改顯示名稱並新增出生日期。如果使用者填寫了顯示名稱,他們可能會在登入後在左上角顯示。
開啟Views/Shared資料夾的_LoginPartial.cshtml,並將前四行替換為以下程式碼段:
@using Microsoft.AspNetCore.Identity
@using AuthSample.Data
@inject SignInManager<WebAppUser> SignInManager
@inject UserManager<WebAppUser> UserManager
@{ var user = await @UserManager.GetUserAsync(User); }
做using部分,將SignInManager和UserManager的泛型引數從IdentityUser型別更改為WebAppUser。
在程式碼塊部分,通過傳入當前使用者,通過UserManager載入當前WebAppUser。
現在,需要更改使用者名稱的輸出以寫入顯示名稱:
Hello @user?.Name!
當dotnet watch仍在執行時,瀏覽器中執行的應用程式應該已經更新。也許你需要重新登入。現在,您應該會在右上角看到顯示名稱:
在本章中,我們學習瞭如何擴充套件ASP.NET Core Identity,通過新增其他屬性來增強使用者物件。我們還學習瞭如何增強Identity UI以載入、儲存和更新新使用者屬性的值。
但是,應該如何管理應用程式使用者的角色?我們將在下一章中學習的關於設定身份管理的內容。