原文: ASP.NET Core 新增使用者 - ASP.NET Core 基礎教程 - 簡單教程,簡單程式設計
ASP.NET Core 新增使用者
上一章節我們實作了一個系統資料庫單,但也留了一些東西還沒完成,就是送出系統資料庫單後的動作。使用 Identity 實作注冊功能,但送出系統資料庫單後,需要做的事情很多,比如與 Identity 架構進行互動,以確定使用者有效,告訴 Identity 架構建立該使用者
在本章節,我們将學習如何建立使用者,如何與 Identity 架構進行互動,以確定使用者有效,然後建立該使用者,最後使用注冊的進行登入操作
所有的這些事情,都與
Identity
架構的兩個核心服務: UserManager 和 SignInManager 有關
我們需要将這兩項服務注入我們的控制器
AccountController
,然後才能在建立使用者或登入使用者時調用相應的 API
首先在
AccountController
控制器中添加兩個使用
User
範型的
SignInManager
和
UserManager
類型的私有變量,然後再建立一個構造函數,用于接收這兩個類型的參數
private SignInManager<User> _signManager;
private UserManager<User> _userManager;
public AccountController(UserManager<User> userManager, SignInManager<User> signManager)
{
_userManager = userManager;
_signManager = signManager;
}
接下來在使用了
[HttpPost]
特性的
Signup
方法中檢查和驗證送出的資料是否有效,主要是通過檢查
ModelState
是否有效
[HttpPost]
public async Task<IActionResult> Signup(RegisterViewModel model) {
if (ModelState.IsValid) {
}
return View();
}
如果
ModelState
有效,則使用
UserName
來建立一個
User
的執行個體,并使用
_userManager
異步儲存使用者名和密碼。
- 如果儲存成功,則使用
直接登入然後跳回首頁_signManager
- 如果儲存失敗,則告知使用者,并讓使用者輸入正确的資料
内容是不是很多,不過反應到代碼上,就寥寥幾行
[HttpPost]
public async Task<IActionResult> Signup(RegisterViewModel model) {
if (ModelState.IsValid) {
var user = new User { UserName = model.Username };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded) {
await _signManager.SignInAsync(user, false);
return RedirectToAction("Index", "Home");
} else {
foreach (var error in result.Errors) {
ModelState.AddModelError("", error.Description);
}
}
}
return View();
}
我們來詳細看看這段代碼
- 如果 ModelState 有效,則使用 UserName 來建立一個 User 的執行個體
- 但是我們并沒有把密碼和傳遞給
,因為User
并沒有屬性來儲存明文密碼,是以我們隻能直接将密碼傳遞給 Identity 架構,架構會自動哈希密碼User
- 為了使用 Identity 架構儲存使用者資料,我們使用
的異步方法UserManager
,該方法接收使用者名和明文密碼,然後使用這些資料建立一個新的使用者CreateAsync
- 異步方法
會傳回一個結構,告訴我們是成功建立了使用者還是失敗了,如果失敗了,會傳回一些失敗的原因CreateAsync
- 如果結果是成功的,就登入剛剛建立帳戶的使用者,且使用 SignInManager 為該使用者簽名,最後将使用者重定向回首頁
- 如果結果不成功,則告訴使用者為什麼,将 UserManager 傳回的錯誤結果疊代添加到 ModelState 中。然後視圖中就可以使用标簽助手 ( 如驗證标簽助手 ) 顯示這些錯誤資訊
-
方法接收一個鍵值對參數,第一個參數為鍵,第二個參數為值,如果鍵是空的,那麼就會把所有錯誤都放在一起ModelState.AddModelError
- 最後,因為我們使用了異步方法,是以傳回結果必須也是異步的,需要使用
async Task<IActionResult>
最後,當然了,為了讓程式能正常運作,我們還需要引入三個命名空間
System.ComponentModel.DataAnnotations
、
System.Threading.Tasks
HelloWorld.Models
,然後删除
AccountController()
空的構造函數
所有這些修改完成後,
AccountController.cs
的代碼如下
using System;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using HelloWorld.Models;
namespace HelloWorld.Controllers
{
public class AccountController : Controller
{
private SignInManager<User> _signManager;
private UserManager<User> _userManager;
public AccountController(UserManager<User> userManager, SignInManager<User> signManager)
{
_userManager = userManager;
_signManager = signManager;
}
[HttpGet]
public ViewResult Signup()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Signup(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new User { UserName = model.Username };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await _signManager.SignInAsync(user, false);
return RedirectToAction("Index", "Home");
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
return View();
}
}
public class RegisterViewModel
{
[Required, MaxLength(64)]
public string Username { get; set; }
[Required, DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password), Compare(nameof(Password))]
public string ConfirmPassword { get; set; }
}
}
注冊示範
現在,我們重新開機應用程式,重新整理浏覽器,來到注冊界面,輸入
yufei
aBc123@456

因為密碼規則必須是 6 個字元以上且包含一個大寫字母和小寫字母,且必須包含一個非數組字母字元,是以如果不是這種格式則會報錯,比如
123
則輸出錯誤如下
注冊成功後就會跳轉到首頁
如果使用 SQLite Studio 打開我們的
blogging.db
資料庫,就可以看到我們剛剛建立的使用者
本章到這裡就已經結束了,我們已經實作了一個相對完整的注冊功能,為啥說是相對完整呢?
- 缺少防惡意和機器注冊機制,也就是應該讓輸入手機号和郵箱然後發送驗證碼
- 缺少驗證碼,這樣可能導緻頻繁的刷接口注冊
- 缺少已登入使用者跳回首頁機制