在前面的篇章介紹中,簡單介紹了IdentityServer4持久化存儲機制相關配置和操做數據,實現了數據遷移,可是未對用戶實現持久化操做說明。在總結中咱們也提到了,html
由於IdentityServer4本就支持了接入其餘認證方式,因此本身根據須要進行合理擴展的,好比咱們可使用 Asp.Net Core 自帶的 Identity 身份認證機制來實現擴展,實現用戶數據持久化操做。mysql
固然了,本篇暫時拋開IdentityServer4這個話題,而是單獨認識一下Asp.Net Core 自帶的 Identity 身份認證機制是什麼樣的?git
所以,本篇主要介紹的是將ASP.NET Core Identity 實戰應用。github
ASP.NET Core Identity是用於構建ASP.NET Core Web應用程序的身份認證系統,包括用戶數據,用戶身份以及註冊登陸信息數據存儲,可讓您的應用擁有登陸功能以及持續化存儲登陸用戶相關數據。web
ASP.NET Core Identity(下文簡稱Identity)能夠簡單的用戶管理系統,可是倒是一個功能強大的系統,包含用戶管理的方方面面,主要包括:正則表達式
具體對於Identity
的理解能夠參考Asp.Net Core之Identity入門sql
接下來咱們主要是實踐應用一下,理解Identity
。數據庫
基於vs2019, .net core3.1建立asp.net core web 應用程序。json
1.選擇「文件」 > 「新建」 > 「項目」。 2.選擇「ASP.NET Core Web應用程序」。 將項目命名WebIdentityDemoV3.0具備項目下載相同的命名空間。 單擊 「肯定」。 3.選擇 ASP.NET Core Web MVC應用程序,而後選擇更改身份驗證。 4.選擇單個用戶賬戶而後單擊肯定。
生成的項目 ASP.NET Core Identity
以類庫形式 Razor 提供。安全
找到appsettings.json文件, ConnectionStrings的數據庫鏈接字符串,默認是鏈接本地的數據庫,固然了,你也能夠改爲你指定的數據庫地址。
"ConnectionStrings": { "DefaultConnection": "Data Source=.;initial catalog=IdentityV3;user id=sa;password=123456;" },
基於生成的遷移代碼,同步到數據庫
PM> Update-Database
到了這裏,咱們基本完成了Identity
項目的搭建了,能夠就此運行登陸註冊。
但是回到生成的目錄結構看來,卻發現沒有Identity
用戶相關的model,cshtml等文件。這是爲什麼呢?
其實這些相關文件已由內置Razor類庫提供。因此生成的代碼目錄沒有。
但實際開發中,咱們須要生成相應的源代碼,以便根據開發需求拓展更改代碼和更改行爲。因此能夠根據net core爲咱們提供的基架標識(Scaffold Identiy)生成須要重寫的文件。
在ASP.NET Core 2.1 及更高版本提供了ASP.NET Core Identity做爲Razor 類庫。 包含Identity的應用程序能夠應用基架,來有選擇地添加包含在Identity Razor 類庫 (RCL) 的源代碼。
1.從對應的項目中,右鍵單擊該項目 >添加 > 新基架項。 2.從左窗格添加基架對話框中,選擇標識 > 添加。 3.在中添加 標識添加對話框中,選擇所需的選項。
下面使用現有的數據上下文,選擇全部文件,以便後面重寫,以下所示。
這裏示例 因此我選擇只添加 Register
、 Login
、 LogOut
和 RegisterConfirmation
文件
生成後,目錄新增變化:
能夠發現,在Areas
目錄下,生成了Razor Page
文件,須要注意的是這不是MVC視圖控制器。
剛剛介紹說了,這是由於在ASP.NET Core 2.1及更高版本提供了ASP.NET Core Identity做爲Razor 類庫,再也不是以前的2.0的類庫, 由於是基於Razor Page的,
因此找不到原來在2.0版本下的
Controllers
(如Account
等控制器)這個時候若是你想該頁面或者的代碼,就須要基於基架重寫文件到你的項目中後,再作具體修改。
可是若是你又想實現MVC這種視圖控制器的話,你能夠基於Razor Page中的,重寫生成對應的控制器及業務邏輯,來實現視圖控制器這種方式。
2.0 版本
看到有人問:.net core mvc模板選我的身份驗證後 Identity區域下Account控制器在哪裏?
其實這是由於在ASP.NET Core 2.1及更高版本提供了ASP.NET Core Identity做爲Razor 類庫,再也不是以前的2.0的類庫, 由於是基於Razor Page的,因此找不到原來在2.0版本下的
Controllers
(如Account
等控制器)
可是若是你又想實現MVC這種視圖控制器的話,你能夠基於Razor Page中的,重寫生成對應的控制器及業務邏輯,來實現視圖控制器這種方式。固然了,你也能夠利用2.0版本的項目進行參考重寫你的業務。
基於vs2019, .net core2.0 建立asp.net core web 應用程序。
1.選擇「文件」 > 「新建」 > 「項目」。 2.選擇「ASP.NET Core Web應用程序」。 將項目命名WebIdentityDemoV2.0具備項目下載相同的命名空間。 單擊 「肯定」。 3.選擇 ASP.NET Core Web MVC應用程序,而後選擇更改身份驗證。 4.選擇單個用戶賬戶而後單擊肯定。
生成的項目 ASP.NET Core Identity
以類庫形式 Razor 提供。
能夠發現, 在咱們選擇我的身份認證的時候 Identity被自動添加到項目中,而且生成了
AccountController
註冊和登錄相關的代碼都在這裏)ManageController
這是給註冊用戶用的,主要有兩個功能,改密碼和雙因子驗證)已經出現了MVC這種視圖控制器,也能夠找到對應的控制器方法了。這也是相比於升級到2.1及更高版本的不一樣之處。
在2.0版本中的MVC視圖控制器模式而升級到2.1及更高版本後,直接採用了Razor類庫,改爲了將控制器寫到了cshtml文件上了。
找到appsettings.json文件, ConnectionStrings的數據庫鏈接字符串,默認是鏈接本地的數據庫,固然了,你也能夠改爲你指定的數據庫地址。
"ConnectionStrings": { "DefaultConnection": "Data Source=.;initial catalog=IdentityV2;user id=sa;password=123456;" },
基於生成的遷移代碼,同步到數據庫
PM> Update-Database
到了這裏,咱們基本完成了2.0 版本的Identity
項目的搭建了,能夠就此運行登陸註冊了。
到了這裏, 咱們也就體驗了Asp.Net Core2.0以及在升級到2.1及更高版本後發生的變化了。
以下是代碼Identity
的默認選項配置,服務經過依賴關係注入提供應用程序。
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); //這裏須要注意的是 options.SignIn.RequireConfirmedAccount 設置項,缺省設置爲true, //這種狀況下,新註冊的用戶須要進行確認才能完成註冊,若是沒有安裝郵件系統,這個步驟沒法完成,因此這裏改成false。 services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false) .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddControllersWithViews(); services.AddRazorPages(); }
經過調用啓用 UseAuthentication
。 UseAuthentication
將身份驗證 中間件 添加到請求管道。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); }
除了上面的默認配置選項之後,你也能夠根據自身的業務要求,好比有些想要對用戶名作限制,有些須要在密碼作限制等等。
典型模式是調用全部
Add{Service}
方法,而後調用全部services.Configure{Service}
方法。
services.AddDefaultIdentity<IdentityUser>(options => { options.User = new UserOptions { RequireUniqueEmail = true, //要求Email惟一 AllowedUserNameCharacters = "abcdefgABCDEFG" //容許的用戶名字符,默認是 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+ }; });
不支持正則表達式,若是須要支持漢字,可能須要添加不少漢字才行。。
services.AddDefaultIdentity<IdentityUser>(options=> { options.Password = new PasswordOptions { RequireDigit = true, //要求有數字介於0-9 之間, 默認true RequiredLength = 8, //要求密碼最小長度, 默認是 6 個字符 RequireLowercase = true, //要求小寫字母, 默認true RequireNonAlphanumeric = true, //要求特殊字符, 默認true RequiredUniqueChars = 3, //要求須要密碼中的非重複字符數, 默認1 RequireUppercase = true //要求大寫字母 ,默認true }; })
services.AddDefaultIdentity<IdentityUser>(options=> { options.Lockout = new LockoutOptions { AllowedForNewUsers = true, // 新用戶鎖定帳戶, 默認true DefaultLockoutTimeSpan = TimeSpan.FromHours(1), //鎖定時長,默認是 5 分鐘 MaxFailedAccessAttempts = 3 //登陸錯誤最大嘗試次數,默認 5 次 }; })
services.AddDefaultIdentity<IdentityUser>(options=> { options.Stores = new StoreOptions { MaxLengthForKeys = 128, // 主鍵的最大長度 ProtectPersonalData = true //保護用戶數據,要求實現 IProtectedUserStore 接口 }; })
若是不設置,主鍵則是 max 的字符串長度。
services.AddDefaultIdentity<IdentityUser>(options=> { options.Tokens = new TokenOptions { AuthenticatorTokenProvider = "MyAuthenticatorTokenProvider", //用於使用驗證器驗證雙重登陸的。 ChangeEmailTokenProvider = "MyChangeEmailTokenProvider", //用於生成電子郵件更改確認電子郵件中使用的令牌的。 ChangePhoneNumberTokenProvider = "MyChangePhoneNumberTokenProvider", //用於生成更改電話號碼時使用的令牌的。 EmailConfirmationTokenProvider = "MyEmailConfirmationTokenProvider", //用於生成賬戶確認電子郵件中使用的令牌的令牌提供程序。 PasswordResetTokenProvider = "MyPasswordResetTokenProvider", //用於生成密碼重置電子郵件中使用的令牌 ProviderMap = new Dictionary<string, TokenProviderDescriptor>(), //用做提供程序名稱的密鑰構造 用戶令牌提供程序 。 AuthenticatorIssuer = "Identity", //認證的消費者 }; })
如何生成令牌,而後用什麼方式將令牌發給用戶,請求用戶驗證。
services.AddDefaultIdentity<IdentityUser>(options=> { options.ClaimsIdentity = new ClaimsIdentityOptions { RoleClaimType = "IdentityRole", // 用於角色聲明的聲明類型。 UserIdClaimType = "IdentityId", // 用於用戶標識符聲明的聲明類型。 SecurityStampClaimType = "SecurityStamp", //用於安全戳聲明的聲明類型。 UserNameClaimType = "IdentityName" //用於用戶名聲明的聲明類型。 }; })
services.AddDefaultIdentity<IdentityUser>(options=> { options.SignIn = new SignInOptions { RequireConfirmedEmail = true, //要求激活郵箱., 默認false RequireConfirmedPhoneNumber = true //要求激活手機號才能登陸,默認false }; })
在登陸的時候,若是手機號或郵箱沒有激活/確認,則沒法登陸。
services.ConfigureApplicationCookie(options => { options.AccessDeniedPath = "/Identity/Account/AccessDenied"; options.Cookie.Name = "YourAppCookieName"; options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(60); options.LoginPath = "/Identity/Account/Login"; // ReturnUrlParameter requires //using Microsoft.AspNetCore.Authentication.Cookies; options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter; options.SlidingExpiration = true; });
在中配置應用 cookie 程序 Startup.ConfigureServices
。 ConfigureApplication Cookie調用或 後必須調用 AddIdentity``AddDefaultIdentity
。
services.Configure<PasswordHasherOptions>(option => { option.IterationCount = 12000; //使用 PBKDF2 對密碼進行哈希處理時使用的迭代次數。 });
PasswordHasherOptions 獲取和設置用於密碼哈希的選項。
services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); });