- ASP.NET Core 教程
- ASP.NET Core - 首頁
- ASP.NET Core - 概述
- ASP.NET Core - 環境設定
- ASP.NET Core - 新建專案
- ASP.NET Core - 專案佈局
- ASP.NET Core - project.json
- ASP.NET Core - 配置
- ASP.NET Core - 中介軟體
- ASP.NET Core - 異常處理
- ASP.NET Core - 靜態檔案
- ASP.NET Core - 設定 MVC
- ASP.NET Core - MVC 設計模式
- ASP.NET Core - 路由
- ASP.NET Core - 屬性路由
- ASP.NET Core - 操作結果
- ASP.NET Core - 檢視
- 設定 Entity Framework
- ASP.NET Core - DbContext
- ASP.NET Core - Razor 佈局檢視
- ASP.NET Core - Razor 檢視啟動
- ASP.NET Core - Razor 檢視匯入
- ASP.NET Core - Razor 標籤助手
- ASP.NET Core - Razor 編輯表單
- ASP.NET Core - Identity 概述
- ASP.NET Core - Authorize 屬性
- Identity 配置
- ASP.NET Core - Identity 遷移
- ASP.NET Core - 使用者註冊
- ASP.NET Core - 建立使用者
- ASP.NET Core - 登入和登出
- ASP.NET Core 有用資源
- ASP.NET Core - 快速指南
- ASP.NET Core - 有用資源
- ASP.NET Core - 討論
ASP.NET Core - 登入和登出
本章將討論登入和登出功能。與登入相比,登出的實現比較簡單。讓我們從佈局檢視開始,因為我們想要構建一個包含一些連結的UI。這將允許已登入使用者登出並顯示使用者名稱。
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@DateTime.Now
</div>
<div>
@RenderBody()
</div>
</body>
</html>
對於匿名使用者,我們將顯示一個登入連結。
構建此UI所需的所有資訊都可從Razor檢視上下文獲取。
首先,讓我們在佈局檢視中新增名稱空間`System.Security.Claims`。
@using System.Security.Claims
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@if (User.IsSignedIn()) {
<div>@User.GetUserName()</div>
<form method = "post" asp-controller = "Account" aspcontroller = "Logout">
<input type = "submit" value = "Logout"/>
</form>
} else {
<a asp-controller = "Account" asp-action = "Login">Login</a>
<a asp-controller = "Account" asp-action = "Register">Register</a>
}
</div>
<div>
@DateTime.Now
</div>
<div>
@RenderBody()
</div>
</body>
</html>
在每個Razor檢視中都可使用一個`User`屬性,我們想要構建一個顯示已登入使用者名稱 的UI。這裡還提供了一個擴充套件方法`IsSignedIn`。
我們可以呼叫此方法,如果它返回true,則可以在此處放置一些標記來顯示使用者名稱,顯示登出按鈕。
現在,如果使用者已登入,我們可以使用輔助方法`GetUserName`顯示使用者的使用者名稱。
我們必須在一個表單內構建登出按鈕,該表單將釋出到Web伺服器。必須這樣做,因為如果允許簡單的GET請求讓使用者退出,則會產生某些不良情況。
我們將強制將其設定為POST請求,當用戶提交此表單時,我們只需要點選登出操作(我們將透過`AccountController`實現),然後登出使用者。
如果使用者未登入並且我們有匿名使用者,則需要顯示一個連結,該連結將轉到`AccountController`,特別是`Login`操作,並且可以顯示文字“登入”。
我們還需要為新使用者新增一個註冊連結,直接跳轉到註冊頁面。
現在讓我們轉到`AccountController`並首先實現登出操作,如下面的程式所示。
[HttpPost]
public async Task<IActionResult> Logout() {
await _signManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}
此操作僅響應HttpPost。這是一個非同步操作。我們必須在Identity框架上呼叫另一個非同步方法。
我們可以返回`IActionResult`的任務,操作名為`Logout`。
登出所需做的就是等待`SignInManager's SignOutAsync`方法。
使用者上下文現在已更改;我們現在有了一個匿名使用者。檢視將重定向到主頁,我們將返回到員工列表。
現在讓我們繼續構建登入功能。這裡,我們需要一對操作,一個響應HttpGet請求並顯示我們可以用來登入的表單,另一個響應HttpPost請求。
首先,我們需要一個新的ViewModel來提取登入資料,因為登入與註冊非常不同。因此,讓我們新增一個新類並將其命名為`LoginViewModel`。
public class LoginViewModel {
public string Username { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name ="Remember Me")]
public bool RememberMe { get; set; }
public string ReturnUrl { get; set; }
}
當用戶登入時,他們必須提供一些資訊,例如使用者名稱、密碼。
第三條資訊必須是登入UI。這些帶有一個小複選框,上面寫著——“您是否要記住我”。這是我們是否想要會話cookie或更永久的cookie的選擇。
為了允許此功能,我們添加了一個布林屬性`RememberMe`,並使用了`Display`特性。現在,當我們構建標籤時,文字“記住我”將帶空格顯示。
我們實際上希望作為此ViewModel一部分的最後一條資訊是擁有一個將儲存`ReturnUrl`的屬性。
現在讓我們新增將響應Get請求的`Login`操作,如下面的程式所示。
[HttpGet]
public IActionResult Login(string returnUrl = "") {
var model = new LoginViewModel { ReturnUrl = returnUrl };
return View(model);
}
我們將`returnUrl`作為查詢字串中的引數。
`returnUrl`可能並不總是存在。讓我們使用空字串作為預設值。
我們現在將透過在`Views → Account`資料夾中新增新的MVC檢視頁面來新增一個新檢視。
在中間窗格中,選擇MVC檢視頁面並將其命名為`Login.cshtml`,然後單擊“新增”按鈕。讓我們在`Login.cshtml`檔案中新增以下程式碼。
@model LoginViewModel
@{
ViewBag.Title = "Login";
}
<h2>Login</h2>
<form method = "post" asp-controller = "Account" asp-action = "Login"
asp-route-returnurl = "@Model.ReturnUrl">
<div asp-validation-summary = "ValidationSummary.ModelOnly"></div>
<div>
<label asp-for = "Username"></label>
<input asp-for = "Username" />
<span asp-validation-for = "Username"></span>
</div>
<div>
<label asp-for = "Password"></label>
<input asp-for = "Password" />
<span asp-validation-for = "Password"></span>
</div>
<div>
<label asp-for = "RememberMe"></label>
<input asp-for = "RememberMe" />
<span asp-validation-for = "RememberMe"></span>
</div>
<input type = "submit" value = "Login" />
</form>
在此登入檢視中,我們將頁面的標題設定為“登入”,然後我們有一個表單,它將釋出到`AccountLogin`操作。
我們需要使用標籤助手`asp-route-returnurl`來確保`ReturnUrl`存在於表單釋出到的URL中。
我們需要將`ReturnUrl`傳送回伺服器,以便如果使用者成功登入,我們可以將其傳送到他們試圖到達的地方。
在`asp-route-`之後新增的任何內容,例如id或returnurl,無論您在那裡有什麼,都將進入請求中的某個位置,要麼進入URL路徑,要麼作為查詢字串引數。
我們有`ValidationSummary`和使用者名稱、密碼和`RememberMe`的輸入,然後我們有一個提交按鈕。
`AccountController`,並實現Post操作。此操作響應HttpPost。這將是一個非同步方法,因為我們需要呼叫Identity框架並返回`IActionResult`的任務。
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model) {
if (ModelState.IsValid) {
var result = await _signManager.PasswordSignInAsync(model.Username,
model.Password, model.RememberMe,false);
if (result.Succeeded) {
if (!string.IsNullOrEmpty(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl)) {
return Redirect(model.ReturnUrl);
} else {
return RedirectToAction("Index", "Home");
}
}
}
ModelState.AddModelError("","Invalid login attempt");
return View(model);
}
我們稱之為`Login`,現在我們期望接收一個`LoginViewModel`。
我們需要檢查`ModelState`是否有效。如果有效,則透過呼叫`SignInManager`上的API來登入使用者。
`PasswordSignInAsync`方法將返回一個結果,如果結果成功,我們就知道使用者已成功登入。
我們還有一個`returnUrl`。如果它是一個有效的本地Url,我們將被重定向到`returnUrl`。
如果使用者剛剛登入並且沒有任何特定的地方要去,我們將把使用者重定向到`HomeController`的`Index`操作。
我們可能遇到使用者提供無效密碼或無效使用者名稱的情況。我們還需要新增一個模型錯誤,提示是否存在無效的登入嘗試。這有助於使用者知道是否出現錯誤。
現在讓我們儲存所有內容並執行應用程式。
我們現在有“登入”和“註冊”連結。讓我們點選“登入”連結。
讓我們使用我們在上一章中建立的使用者登入,指定`使用者名稱`和`密碼`,並選中`記住我`複選框。
單擊“登入”按鈕時,瀏覽器會詢問您是否要儲存localhost的密碼。讓我們單擊“是”按鈕。
現在,讓我們透過單擊“登出”按鈕登出。
作為匿名使用者,讓我們嘗試編輯員工詳細資訊。
您現在可以看到我們已被重定向到`Login`檢視。
讓我們使用您的使用者名稱和密碼登入,並選中“記住我”複選框。
現在,單擊“登入”按鈕。
您現在可以看到我們被定向到我們想要編輯的URL。這是因為我們適當地處理了`returnUrl`。