快速掌握 ASP.NET 身份認證框架 Identity - 用戶注冊

推薦關注「碼俠江湖」星標,時刻不忘江湖事

這是 ASP.NET Core Identity 系列的第二篇文章,上一篇文章介紹了 Identity 框架的集成,以及一些基礎知識。

這篇文章講一講如何在 ASP.NET Core Identity 中實現用戶注冊。

點擊上方或后方藍字,閱讀 ASP.NET Core Identity 系列合集。

本篇文章的示例項目:https://github.com/zilor-net/IdentitySample/tree/main/Sample02

46acd8c7757979144a8f344273565dee.png

準備工作

ASP.NET Core Identity 提供了很多不同的身份選項,幫助我們實現用戶注冊。

首先,讓我們在 「Models」 文件夾中,創建一個用戶注冊模型:

public?class?UserRegistrationModel
{[Display(Name?=?"姓氏")]public?string?FirstName?{?get;?set;?}[Display(Name?=?"名字")]public?string?LastName?{?get;?set;?}[Display(Name?=?"電子郵箱")][Required(ErrorMessage?=?"電子郵箱不能為空")][EmailAddress]public?string?Email?{?get;?set;?}[Display(Name?=?"密碼")][Required(ErrorMessage?=?"密碼不能為空")][DataType(DataType.Password)]public?string?Password?{?get;?set;?}[Display(Name?=?"確認密碼")][DataType(DataType.Password)][Compare("Password",?ErrorMessage?=?"密碼與確認密碼不匹配。")]public?string?ConfirmPassword?{?get;?set;?}
}

這個類中的屬性,需要用戶在注冊表單中填寫。

其中,EmailPassword 屬性是必需的,ConfirmPassword 屬性的值必須與 Password 屬性的值匹配。

有了這個模型,我們再來創建一個 「Account」 控制器:

public?class?AccountController?:?Controller
{[HttpGet]public?IActionResult?Register(){return?View();}[HttpPost][ValidateAntiForgeryToken]public?IActionResult?Register(UserRegistrationModel?userModel){return?View();}
}

它有兩個 Register 操作方法,用來提供用戶注冊功能。

第一個 Register 方法接受 Get 請求,用來顯示注冊表單的視圖;

第二個 Register 方法接受 Post 請求,用來處理用戶注冊邏輯,并顯示注冊結果的視圖。

還需要為 GET Register 操作,創建一個視圖,這里我們可以直接使用 Create 模板,模型類選擇 UserRegistrationModel 類即可。

5a8f805151b658c18bcc9cf63938bb4c.png

現在這個視圖中的表單,已經可以為用戶注冊模型,提供所有的輸入字段了。

需要注意的是,我們最好修改表單中 asp-validation-summary 的值為 All

因為,默認情況下,它只能顯示模型驗證產生的錯誤信息,而不會顯示我們自己設置的驗證錯誤。

視圖中的 Create 按鈕,會跳轉到 POST 請求的 Register 操作方法,并且填充用戶注冊模型。

在 Web API 中使用來自用戶的數據,最好采用數據傳輸對象的方式,但是在 MVC 中不一定如此。

這是因為 MVC 有模型的存在,在有視圖的情況下,模型在一定程度上,替代了數據傳輸對象職責。

由于我們的數據通過視圖傳遞,因此該類模型也被稱為視圖模型。

「UserRegistrationModel」 就是一個視圖模型,如果我們想要真正的在數據庫中存儲它,必須要把它映射到 User 實體類。

我們需要安裝 AutoMapper :

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

然后,在 Program 類中注冊它:

builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());

接著,在布局頁的導航菜單上,添加一個注冊按鈕。

因為后面還要添加登錄按鈕,所以為了代碼的可維護性,我們可以創建一個分部視圖:

//?Shared\_LoginPartial.cshtml<ul?class="navbar-nav"><li?class="nav-item"><a?class="nav-link?text-dark"?asp-controller="Account"?asp-action="Register">注冊</a>????</li>
</ul>

最后,修改 「_Layout.cshtml」 布局視圖,在導航菜單上添加登錄分布視圖:

<div?class="navbar-collapse?collapse?d-sm-inline-flex?flex-sm-row-reverse"><partial?name="_LoginPartial"?/><!--?添加?--><ul?class="navbar-nav?flex-grow-1">

注冊操作

準備工作都已經完成了。

現在,讓我們從用戶注冊邏輯開始。

首先,必須在 「Account」 控制器中,注入 AutoMapperUserManager 類:

private?readonly?IMapper?_mapper;
private?readonly?UserManager<User>?_userManager;
public?AccountController(IMapper?mapper,?UserManager<User>?userManager)
{_mapper?=?mapper;_userManager?=?userManager;
}

「UserManager」 由 Identity 框架提供,它負責幫助我們管理應用程序中的用戶。

用戶注冊邏輯在 Post 請求的 Register 方法中實現:

[HttpPost]
[ValidateAntiForgeryToken]
public?async?Task<IActionResult>?Register(UserRegistrationModel?userModel)
{if(!ModelState.IsValid){return?View(userModel);}var?user?=?_mapper.Map<User>(userModel);var?result?=?await?_userManager.CreateAsync(user,?userModel.Password);if(!result.Succeeded){foreach?(var?error?in?result.Errors){ModelState.TryAddModelError(error.Code,?error.Description);}return?View(userModel);}await?_userManager.AddToRoleAsync(user,?"Guest");return?RedirectToAction(nameof(HomeController.Index),?"Home");
}

這里需要注意的是,我們把這個方法改成了異步的,因為 ·UserManager· 的助手方法也是異步的。

在方法內部,先檢查模型的有效性,如果它是無效的,就返回帶有無效模型的相同視圖。

如果檢查通過,就將 userModel 射到 user 實體。

使用 CreateAsync 方法用來注冊用戶,它會對密碼進行哈希后保存。

之后,檢查它返回的創建結果。

如果創建成功,我們只需在 UserManager 的幫助下,使用 AddToRoleAsync 方法,給用戶添加一個默認的角色,并將用戶重定向到 Index 頁面。

但是如果注冊失敗,就遍歷所有的錯誤,并將它們添加到 ModelState 中。

前面我們已經將視圖的驗證信息摘要改為了 All,否則這里添加的錯誤,不會顯示出來。

最后,不要忘記創建 AutoMapper 的映射配置類:

//?MappingProfile.cspublic?class?MappingProfile?:?Profile
{public?MappingProfile(){CreateMap<UserRegistrationModel,?User>().ForMember(user?=>?user.UserName,?expression?=>?expression.MapFrom(userModel?=>?userModel.Email));}
}

這里我們把電子郵件映射到用戶名,因為我們在注冊表單中沒有提供用戶名的字段。

現在啟動應用,測試一下用戶注冊。

我可以嘗試各種錯誤的注冊內容,觀察驗證結果。

需要注意的是,默認的密碼驗證規則,非常的復雜,它不但要求有大小寫字母,還必須要求你有一個特殊符號。

這個密碼規則很不錯,但是有時候我可能并不需要強規則。

而且我們使用了電子郵件作為用戶名,但是默認情況下,沒有要求電子郵件是唯一的。

所以,我們可以改變這些規則,這需要在注冊 Identity 的地方,通過配置選項修改:

services.AddIdentity<User,?IdentityRole>(options?=>{options.Password.RequiredLength?=?6;options.Password.RequireDigit?=?false;options.Password.RequireUppercase?=?false;options.Password.RequireNonAlphanumeric?=?false;options.Password.RequireLowercase?=?false;options.User.RequireUniqueEmail?=?true;})
.AddEntityFrameworkStores<ApplicationContext>();

比如,我們這里取消了數字、大寫字母和特殊字符的驗證,最小長度改為 6 位,同時設置電子郵件的唯一驗證。

現在我們再來啟動應用,測試一下注冊過程,比如錯誤的密碼格式、重復的電子郵箱。

大家通過一些測試可以發現,有些錯誤信息是中文的、有些則是英文的。

因為這個錯誤分為兩種類型,一種是我們自定義的模型驗證錯誤,我們已經設置了錯誤的信息,所以這種類型是中文的。

另一種是 ASP.NET Core Identity 內置的驗證錯誤,它是我們通過在操作方法中,自己讀取并添加進模型狀態的。

因為 ASP.NET Core Identity 是英文版的,所以我們獲取到的是英文信息,

不過,我們也可以自行定義中文信息,這需要我們創建一個自定義的錯誤描述類:

public?class?CustomIdentityErrorDescriber?:?IdentityErrorDescriber
{public?override?IdentityError?PasswordTooShort(int?length){return?new(){Code?=?nameof(PasswordTooShort),Description?=?$"密碼至少需要?{length}?位"};}public?override?IdentityError?DuplicateEmail(string?email){return?new(){Code?=?nameof(DuplicateUserName),?Description?=?$"電子郵箱?{email}?已存在。"};}public?override?IdentityError?DuplicateUserName(string?username){return?new(){Code?=?nameof(DuplicateUserName),?Description?=?$"用戶名?{username}?已存在。"};}

自定義的錯誤信息,需要通過覆寫 「IdentityErrorDescriber」 基類的錯誤方法,設置你想要的錯誤描述。

需要的話,你可以通過閱讀源碼,找到所有的錯誤方法。

我們還需要把它配置到注冊 Identity 服務的方法中:

AddErrorDescriber<CustomIdentityErrorDescriber>()

小結

現在,我們已經實現了用戶注冊,具體的代碼可以參看示例項目,下篇文章將會繼續講解用戶登陸以及身份認證。

更多精彩內容,請關注我▼▼

5bc5756b77a8671cb9d5d29913cf1172.gif

如果喜歡我的文章,那么

在看和轉發是對我最大的支持!

(戳下面藍字閱讀)

d07925ccd5e268e0814287d660691a6c.png

推薦關注微信公眾號:碼俠江湖

? ? ? ? ? ? ? ? ? ? ? ??8b2e3e41862831cde44bda4b32836e69.png覺得不錯,點個在看再走喲

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/285789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285789.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android命令Monkey壓力測試,詳解

支持原創&#xff0c;前半部分來源博客原文&#xff1a;http://blog.csdn.net/huangbiao86/article/details/8490743shell, monkey, system, Android, 文件系統Monkey, 示例, 簡介一、Monkey測試簡介Monkey測試是Android平臺自動化測試的一種手段&#xff0c;通過Monkey程序模擬…

JAVA 排序工具類

提供了以下排序&#xff1a; 冒泡排序選擇排序插入排序希爾排序快速排序歸并排序桶排序堆排序package com.xingej.algorithm.sort;import java.util.ArrayList; import java.util.Collections;/*** 排序工具類* * author erjun 2017年12月13日 上午8:38:22*/public class SortU…

js中null,undefined,false,0,'',[],{}判斷方法

目錄 1.數據類型 2.JSON字符串 3.數字類型 4.非的布爾值 5.與非比較 一、單獨判斷 1.null 2.undefined 3.0 4.“” 5.判斷undefined、null與NaN: 因為獲取到數據的不確定性&#xff0c;常常會導致一些異常情況&#xff0c;使得頁面報錯&#xff0c;往往要兼容這些異…

【GIS風暴】30米分辨率地表覆蓋數據GlobeLand30原始數據集簡介及下載地址

數據集預覽&#xff1a; GlobeLand30是30米空間分辨率全球地表覆蓋數據&#xff0c;目前可供下載使用的有3年的數據&#xff1a;2000-2010-2020&#xff0c;本文主要講述GlobeLand30的官網下載地址和數據集簡介。 數據處理方法、成果數據下載&#xff1a; 【ArcGIS風暴】ArcGI…

Git之解決git stash pop多次產生的文件沖突問題

1、問題 我們用git命令一般拉取線上代碼的時候&#xff0c;本地修改了&#xff0c;我們一般先git stash下&#xff0c;接下來git pull, 然后git stash pop下&#xff0c;但是我新增了文件&#xff0c;沒有添加到本地git(也就是沒有git add file這個新增加的文件)&#xff0c;然…

記一次意外

今天嘗試給同一個對象綁定多個事件: document.getElementById("a").οnfοcus function(){ alert("1") }.οnclick function(){ alert("2") } 發現彈出2&#xff0c;改變focus和click的順序后依舊如此&…

一、基礎折線圖詳解《手把手教你 ECharts 數據可視化詳解》

注&#xff1a;本系列教程需要對應 JavaScript 、html、css 基礎&#xff0c;否則將會導致閱讀時困難&#xff0c;本教程將會從 ECharts 的官方示例出發&#xff0c;詳解每一個示例實現&#xff0c;從中學習 ECharts 。 ECharts 官方示例&#xff1a;https://echarts.apache.o…

NLog自定義Target之MQTT

NLog是.Net中最流行的日志記錄開源項目(之一)&#xff0c;它靈活、免費、開源官方支持文件、網絡(TCP、UDP)、數據庫、控制臺等輸出社區支持Elastic、Seq等日志平臺輸出實時日志需求在工業物聯網等特定場景下需要實時獲取日志信息工業物聯網領域常用的是mqtt協議那我們就使用NL…

2016-1-27

2019獨角獸企業重金招聘Python工程師標準>>> 1.前端的三大技能:1.1.描述網頁內容html 1.2.描述網頁樣式css 1.3.描述網頁行為js2.html和jsp區別在于靜態和動態..bootsharp是目前比較火爆的css..angular是目前比較火爆的js.3.單點登陸(SSO):登陸一次就可以訪問所有相…

【ArcGIS風暴】ArcGIS生成GlobeLand30土地利用數據集中國區域行列號shp格式對照圖(附shp下載)

效果預覽: 本文主要講述了在ArcGIS中生成GlobeLand中國區域對照行列號的shp格式矢量數據,用途在于將自己的研究區跟行列號矢量圖層直接疊加顯示,快速找出自己所需要的圖幅號,便于快速下載數據。同時為了方便使用,本文提供了對照圖的下載。 文章目錄 1. 創建文件數據庫2. 創…

Android 節操視頻播放器jiecaovideoplayer自定義播放音頻使用:屏蔽全屏按鈕,增加倒計時,當前時間/總時間

一、屏蔽全屏按鈕 找到JCVideoPlayerStandard.java文件中的代碼&#xff1a; private void fixAudio() {if (SrcType.equalsIgnoreCase("Audio")) {//如果是音頻&#xff0c;始終顯示coverImageView//thumbImageView.setVisibility(View.VISIBLE);coverImageView.se…

Android之Dialog提示Unable to add window -- token is not valid; is your activity running?

1、問題 Dialog奔潰提示Unable to add window -- token android.os.BinderProxy@b251dbc is not valid; is your activity running? 2、解決辦法 傳遞context到dialog的時候,要記得先判斷狀態是不是isFinishing或者isDestroyed狀態,這個時候就不要再去show相關的dialog了,…

nagios監控haproxy(借助腳本)

nagios監控haproxy&#xff08;借助腳本&#xff09; 修改后的腳本如下&#xff08;需添加指示燈的狀態&#xff09; # vi haproxy.sh #!/bin/bash Portnetstat -ntpl | grep haproxy | awk -F[:" "] {print $5} if [ $Port "1080" ];then echo "OK …

一、Qt初嘗試,做一個QT計算器《QT 入門到實戰》

學習目標 了解 qt 的基本信息了解 qt 的下載及安裝了解創建一個基本 qt 項目的流程了解信號與槽通過示例了解信號與槽的設置與編寫了解控件添加的方式了解控件如何使用代碼獲取其文本了解控件如何使用代碼設置其文本使用 connect 自定義信號與槽了解使用樣式修飾控件外觀了解使…

VS C#語言獲取輸入名稱的漢語拼音簡拼碼和全拼碼完整案例教程

結果預覽: 擴展閱讀: SQL語言獲取拼音碼:SQL Server編寫函數獲取漢字的拼音碼(簡拼) 文章目錄 1. 拼音碼類編寫2. 界面設計3. 前端調用4. 結果展示1. 拼音碼類編寫 打開Visual Studio,新建一個Winform項目,再添加一個類文件,命名為PYM。 鍵入如下代碼: using Syst…

iOS duplicate symbol for architecture arm64 解決辦法

導致這個問題的原因有多種&#xff1a; 1.重復定義了const常量。 2.多個第三方庫同時用到了某個函數庫。 暫時列舉這幾種&#xff0c;以后遇到了其他原因再加。轉載于:https://www.cnblogs.com/zhanglinfeng/p/5987077.html

WPF 實現星空效果

本文經原作者授權以原創方式二次分享&#xff0c;歡迎轉載、分享。原文作者&#xff1a;普通的地球人原文地址&#xff1a;https://www.cnblogs.com/tsliwei/p/6282183.htmlGithub地址&#xff1a;https://github.com/WPFDevelopersOrg/WPFDevelopers效果前陣子看到ay的蜘蛛網效…

data類型的Url的格式

data類型的Url的格式 一、data類型的簡介 所謂"data"類型的Url格式&#xff0c;是在RFC2397中提出的&#xff0c;目的對于一些“小”的數據&#xff0c;可以在網頁中直接嵌入&#xff0c;而不是從外部文件載入。例如對于img這個Tag&#xff0c;哪怕 這個圖片非常非…

C語言試題八十之統計單詞個數

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 終端輸入一…

SSIS 執行變量中的腳步輸出列順序與SQL查詢列順序不同

這個問題是朋友遇到的&#xff0c;做一個SSIS的程序將數據導入到txt。然后再用Oracle的工具導入到Oracle。但是在SSIS中執行變量腳步的時候&#xff0c;發現輸出的列名稱跟查詢的列名稱完全不同。比如Schema_id在查詢的第三列&#xff0c;但是輸出的時候到了第6列。 如圖&#…