首先是創建啓動單元:App_Start目錄中的Startup.Auth.cshtml
using Microsoft.AspNet.Identity; using Microsoft.Owin; using Microsoft.Owin.Security.Cookies; using Owin; namespace VonPortal { public partial class Startup { // 有關配置身份驗證的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkId=301864 public void ConfigureAuth(IAppBuilder app) { // 使應用程序可使用 Cookie 來存儲已登陸用戶的信息 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), CookieHttpOnly = true, CookieName = "_VonPortalTicketID" }); // Use a cookie to temporarily store information about a user logging in with a third party login provider app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); } } }
創建用戶用戶信息結構:
jquery
#region "人員基本信息信息類聲明" namespace VonPortal.Web.Models { /// <summary>人員基本信息 信息類</summary> public class UserInfo : IUser<int> { //這個是實現IUser接口的 public int Id { get { return ID; } } #region "Public Properties" /// <summary>序號</summary> [Required] [Display(Name = "序號")] public int ID { get; set; } /// <summary>登陸名</summary> [Required] [Display(Name = "登陸名")] public string UserName { get; set; } /// <summary>電子郵箱</summary> [Required] [Display(Name = "電子郵箱")] public string EMail { get; set; } ...這裏我省略掉和登陸無關信息 /// <summary>登陸口令</summary> [Display(Name = "登陸口令")] public string Password { get; set; } #endregion [Display(Name = "是否記憶登陸信息")] public bool RememberMe { get; set; } } } #endregio #region "人員基本信息信息基礎控制類聲明" namespace VonPortal.Web.Controller { /// <summary>人員基本信息 控制類</summary> public class UserCtrl { //Read data and write to UserInfo class private void setInfoValue(IDataReader reader, UserInfo info) { info.ID = reader.GetInt32(0); //序號 info.UserName = reader.GetString(1); //登陸名 ... } /// <summary>檢驗User信息</summary> public string Check(UserInfo info) { string errInfo = ""; if (info.UserName == "") errInfo = "登陸名稱必須錄入"; if (info.UserName.Length < 8) errInfo = "登陸名不容許少於8個子"; if (info.Password == "") errInfo = "登陸口令必須錄入"; if (info.Password.Length < 8) errInfo = "登陸口令不容許少於8個子"; return errInfo; } /// <summary> /// 根據主鍵 PK_User 提取信息 /// </summary> /// <param name="int ID>序號</param> public UserInfo GetByUser(int ID) { ...省略數據庫提取部分 } /// <summary>根據主鍵 IDX_SHORTNAME 提取信息</summary> /// <param name="string Name>登陸名</param> public UserInfo GetByName(string Name) { ...省略數據庫提取部分 } /// <summary>根據主鍵 IDX_SHORTNAME 提取信息</summary> /// <param name="string Email>電子郵箱</param> public UserInfo GetByEmail(string Email) { ...省略數據庫提取部分 } /// <summary>保存User信息</summary> ///<param name="UserInfo info">信息類</param> public bool Save(UserInfo info) { ...省略數據庫提取部分 } /// <summary>添加User信息</summary> ///<param name="UserInfo info">信息類</param> public int Add(UserInfo info) { ...省略數據庫提取部分 } /// <summary>修改User信息</summary> ///<param name="UserInfo info">信息類</param> public bool Edit(UserInfo info) { ...省略數據庫提取部分 } /// <summary>根據PK_User刪除User信息</summary> /// <param name="int ID>序號</param> public int Del(int ID) { ...省略數據庫提取部分 } } } #endregion #region "人員基本信息信息操做控制類聲明" namespace VonPortal.Web.Tasks { /// <summary>人員基本信息 控制類</summary> public class UserTask : UserCtrl { /// <summary>含數據庫事務的構造函數</summary> public UserTask(IDbTransaction DBTrans) : base(DBTrans) { } /// <summary> /// 根據主鍵 PK_User 提取信息 /// </summary> /// <param name="ID">序號</param> public new Task<UserInfo> GetByUser(int ID) { return Task.Run(() => { return base.GetByUser(ID); }); } /// <summary>根據主鍵 IDX_USER 提取信息</summary> /// <param name="LoginName">登陸名</param> public new Task<UserInfo> GetByName(string LoginName) { return Task.Run(() => { return base.GetByName(LoginName); }); } /// <summary>根據主鍵 IDX_EMAIL 提取信息</summary> /// <param name="EMail">電子郵箱</param> public new Task<UserInfo> GetByEmail(string EMail) { return Task.Run(() => { return base.GetByEmail(EMail); }); } ...相似代碼省略 } } #endregion
這樣就完成了基礎設置工做,即開啓了Owin的認證機制,同時完成了基礎用戶信息,及其訪問數據庫查詢等基礎功能。算法
UserInfo是用戶信息類,UserCtrl是用戶信息控制和存儲基礎單元,UserTask繼承了UserCtrl,同時實現了異步訪問功能,訪問這些函數時,須要 await 來進行。數據庫
好了,基礎作完了我就要進一步分析Owin的機制來一步一步的實現認證功能了c#
先寫一個頁面功能Model,這樣先把頁面做完,就能夠進行測試了。
數組
這個是在Models中的AccountViewModel.cs緩存
using System.ComponentModel.DataAnnotations; namespace VonPortal.Web.Models { public class LoginViewModel { [Required] [Display(Name = "電子郵件")] [EmailAddress] public string Email { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "密碼")] public string Password { get; set; } [Display(Name = "記住我?")] public bool RememberMe { get; set; } } public class ExternalLoginListViewModel { public string ReturnUrl { get; set; } } }
下面是Views中的Account中的Login.cshtml安全
@model VonPortal.Web.Models.RegisterViewModel @{ ViewBag.Title = "註冊"; } <h2>@ViewBag.Title。</h2> @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() <h4>建立新賬戶。</h4> <hr /> @Html.ValidationSummary("", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) </div> </div> <div class="form-group"> @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) </div> </div> <div class="form-group"> @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" class="btn btn-default" value="註冊" /> </div> </div> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
還須要一個_ExternalLoginsListPartial.cshtml擴展頁面文件,這個若是採用MVC創建的工程,都會有的cookie
@model VonPortal.Web.Models.ExternalLoginListViewModel @using Microsoft.Owin.Security <h4>使用其餘服務登陸。</h4> <hr /> @{ var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); if (loginProviders.Count() == 0) { <div> <p> 沒有配置外部身份驗證服務。有關設置此 ASP.NET 應用程序 以支持經過外部服務登陸的詳細信息,請參閱<a href="http://go.microsoft.com/fwlink/?LinkId=403804">此文</a>。 </p> </div> } else { using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl })) { @Html.AntiForgeryToken() <div id="socialLoginList"> <p> @foreach (AuthenticationDescription p in loginProviders) { <button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="使用你的 @p.Caption 賬戶登陸">@p.AuthenticationType</button> } </p> </div> } } }
這樣基礎就OK了,對了,還要一個處理VIew的Controller類,這個類在Controllers目錄中,AccountController.csapp
using Microsoft.AspNet.Identity; using Microsoft.Owin; using Microsoft.Owin.Security; using Microsoft.AspNet.Identity.Owin; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using VonPortal.Web.Models; /****************************************************************************************************************** * 這個類是專門處理View相應的 * ***************************************************************************************************************/ namespace VonPortal.Web.Controllers { [Authorize] public class AccountController : System.Web.Mvc.Controller { /// <summary> /// 構造函數 /// </summary> public AccountController() { } /// <summary> /// IAuthenticationManager的實現類函數 /// </summary> public IAuthenticationManager AutherticationManager { get { return HttpContext.GetOwinContext().Authentication; } } /// <summary> /// 登陸 /// </summary> /// <param name="user"></param> /// <returns></returns> [AllowAnonymous] [HttpGet] public ActionResult Login() { //若是已經驗證,在直接訪問,若是沒有驗證則須要進行登陸 if (AutherticationManager.User.Identity.IsAuthenticated) { return RedirectToAction("index", "home"); } return View(); } //} /// <summary> /// 登陸相應事件 /// </summary> /// <param name="user">Models中定義的頁面元素Model</param> /// <returns></returns> [HttpPost] [AllowAnonymous] public async Task<ActionResult> Login(LoginViewModel user) { if (string.IsNullOrEmpty(user.Email)) { return View(); } if (string.IsNullOrEmpty(user.Password)) { return View(); } //Context IOwinContext OwinContext = HttpContext.GetOwinContext(); //實例化UserStore對象 VonUserStore userStore = new VonUserStore(); //UserManager VonUserManager UserManager = new VonUserManager(userStore); //signInManager VonSignInManager signInManager = new VonSignInManager(UserManager, AutherticationManager); //登陸 SignInStatus SignInStatus = await signInManager.PasswordSignInAsync(user.Email, user.Password, true, shouldLockout: false); //狀態 switch (SignInStatus) { //成功 case Microsoft.AspNet.Identity.Owin.SignInStatus.Success: //標示 //System.Security.Claims.ClaimsIdentity identity = UserManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie); //受權登錄 //AutherticationManager.SignIn(new Microsoft.Owin.Security.AuthenticationProperties { IsPersistent = true }, identity); return RedirectToAction("index", "home"); //鎖定 case Microsoft.AspNet.Identity.Owin.SignInStatus.LockedOut: Response.Write("LockedOut!"); break; //要求驗證 case Microsoft.AspNet.Identity.Owin.SignInStatus.RequiresVerification: Response.Write("RequiresVerification!"); break; //登陸失敗 case Microsoft.AspNet.Identity.Owin.SignInStatus.Failure: Response.Write("Failure!"); break; } return View(@user); } } }
無論其餘錯誤,先進行到這裏,首先咱們完成了全部外圍工做,創建了用戶信息的基礎類,以及操做類,能夠完成信息的數據庫提取、存儲、刪除等工做,同時完成登陸頁面作須要的View-Model-Controller,這樣剩下的就是Owin的核心擴展了,完成Owin和這些信息的交互工做。下圖是系統訪問的邏輯關係。
那麼我就一步一步來實現,首先要創建一個UserManager的類,咱們把它存儲到Models目錄中,VonUserManager.cs
// 實現密碼的哈希算法 using Microsoft.AspNet.Identity; using System; using System.Security.Cryptography; namespace VonPortal.Web.Models { public class VonUserManager : UserManager<UserInfo, int> { /// <summary> /// 構造函數 /// </summary> /// <param name="store"></param> public VonUserManager(VonUserStore store) : base(store) { this.PasswordHasher = new OldSystemPasswordHasher(); } /// <summary> /// Use Custom approach to verify password /// </summary> public class OldSystemPasswordHasher : PasswordHasher { /// <summary> /// 對密碼進行Hash加密 /// </summary> /// <param name="password"></param> /// <returns></returns> public override string HashPassword(string password) { byte[] salt; byte[] buffer2; if (password == null) { throw new ArgumentNullException("password"); } using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8)) { salt = bytes.Salt; buffer2 = bytes.GetBytes(0x20); } byte[] dst = new byte[0x31]; Buffer.BlockCopy(salt, 0, dst, 1, 0x10); Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20); return Convert.ToBase64String(dst); } /// <summary> /// 重寫驗證密碼的方法 /// </summary> /// <param name="hashedPassword">加密後的密碼</param> /// <param name="providedPassword">提供的密碼</param> /// <returns></returns> public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) { byte[] buffer4; if (hashedPassword == null) { return PasswordVerificationResult.Failed; } if (string.IsNullOrEmpty(providedPassword)) { throw new ArgumentNullException("providedPassword"); } byte[] src = Convert.FromBase64String(hashedPassword); if ((src.Length != 0x31) || (src[0] != 0)) { return PasswordVerificationResult.Failed; } byte[] dst = new byte[0x10]; Buffer.BlockCopy(src, 1, dst, 0, 0x10); byte[] buffer3 = new byte[0x20]; Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20); using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(providedPassword, dst, 0x3e8)) { buffer4 = bytes.GetBytes(0x20); } if (ByteEqual(buffer3, buffer4)) { return PasswordVerificationResult.Success; } else { return PasswordVerificationResult.Failed; } } /// <summary> /// 比較兩個字節數組 /// </summary> /// <param name="b1"></param> /// <param name="b2"></param> /// <returns></returns> private static bool ByteEqual(byte[] b1, byte[] b2) { if (b1.Length != b2.Length) return false; if (b1 == null || b2 == null) return false; for (int i = 0; i < b1.Length; i++) { if (b1[i] != b2[i]) { return false; } } return true; } } } }
咱們能夠看到VonUserManager是實現了UserInfo,同時制定UserInfo的主鍵類型是Int類型
public class VonUserManager : UserManager<UserInfo, int>
再注意他的構造函數,他構造時須要綁定一個數據庫存儲的訪問類VonUserStore,這個咱們立刻就要實現,也就是說,在VonUserManager構造時,其實就已經綁定數據的訪問類了,這個類會在系統須要時直接進行調用,不須要咱們在編寫程序來組織了。
/// <summary> /// 構造函數 /// </summary> /// <param name="store"></param> public VonUserManager(VonUserStore store) : base(store) { this.PasswordHasher = new OldSystemPasswordHasher(); }
那麼咱們就來實現VonUserStore,一樣咱們存儲到Models目錄中,VonUserStore.cs
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using VonPortal.Web.Tasks; /****************************************************************************************************************** * 這是 Owin 調用的數據庫訪問基礎類 * IUserStore<UserInfo, int>, 實現人員信息的基本操做 * (CreateAsync,DeleteAsync,FindByIdAsync,UpdateAsync)即增刪改查 * IUserPasswordStore<UserInfo, int> 實現密碼的轉換 * (GetPasswordHashAsync,HasPasswordAsync,SetPasswordHashAsync) * IUserClaimStore<UserInfo, int> 實現系統緩存功能 * (AddClaimAsync,GetClaimsAsync,RemoveClaimAsync) * IUserLockoutStore<UserInfo, int> 獲得登陸限制信息,在嘗試必定的失敗次數後容許鎖定一個帳號 * (GetAccessFailedCountAsync,GetLockoutEnabledAsync,GetLockoutEndDateAsync,IncrementAccessFailedCountAsync,ResetAccessFailedCountAsync,SetLockoutEnabledAsync,SetLockoutEndDateAsync) * IUserEmailStore<UserInfo, int> 獲得Email的存儲方法,使用郵件地址作確認 (例如經過郵件進行確認) * (FindByEmailAsync,GetEmailAsync,GetEmailConfirmedAsync,SetEmailAsync,SetEmailConfirmedAsync) * IUserPhoneNumberStore<UserInfo, int> 獲得電話號碼的存儲方法,使用手機號碼作確認(例如經過短信進行確認) * (GetPhoneNumberAsync,GetPhoneNumberConfirmedAsync,SetPhoneNumberAsync,SetPhoneNumberConfirmedAsync) * IUserTwoFactorStore<UserInfo, int> 啓用2中途徑進行安全驗證 (例如經過用戶名/密碼和經過郵件或者短信的令牌),當用戶密碼可能存在不安全隱患的時候,系統會以短信或郵件的方式向用戶發送安全碼 * (GetTwoFactorEnabledAsync,SetTwoFactorEnabledAsync) ** ***************************************************************************************************************/ namespace VonPortal.Web.Models { public class VonUserStore : IUserStore<UserInfo, int>, IUserPasswordStore<UserInfo, int>, IUserClaimStore<UserInfo, int>, IUserLockoutStore<UserInfo, int>, IUserEmailStore<UserInfo, int>, IUserPhoneNumberStore<UserInfo, int>, IUserTwoFactorStore<UserInfo, int> { /// <summary> /// 聲明 /// </summary> public IList<System.Security.Claims.Claim> Claims = null; /// <summary> /// 實例化 /// </summary> public VonUserStore() { //聲明 Claims = new List<System.Security.Claims.Claim>(); } /// <summary> /// 用戶 /// </summary> public UserInfo UserIdentity = null; /// <summary> /// 建立用戶 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task CreateAsync(UserInfo user) { return (new UserTask(null)).Add(user); } /// <summary> /// 刪除用戶 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task DeleteAsync(UserInfo user) { return (new UserTask(null)).Del(user.ID); } /// <summary> /// 2>經過用戶ID,獲取用戶 /// </summary> /// <param name="userId"></param> /// <returns></returns> public Task<UserInfo> FindByIdAsync(int userId) { return (new UserTask(null)).GetByUser(userId); } /// <summary> /// 1>經過用戶名獲取用戶信息 /// </summary> /// <param name="userName"></param> /// <returns></returns> public Task<UserInfo> FindByNameAsync(string userName) { return (new UserTask(null)).GetByName(userName); } /// <summary> /// 更新用戶信息 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task UpdateAsync(UserInfo user) { return (new UserTask(null)).Edit(user); } /// <summary> /// 釋放 /// </summary> public void Dispose() { throw new NotImplementedException(); } /// <summary> /// 獲取密碼 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPasswordHashAsync(UserInfo user) { return Task<string>.Run(() => { return user.Password; }); } /// <summary> /// 是否有密碼 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> HasPasswordAsync(UserInfo user) { return Task.FromResult<bool>(!string.IsNullOrEmpty(user.Password)); } /// <summary> /// 密碼進行加密 /// </summary> /// <param name="user"></param> /// <param name="passwordHash"></param> /// <returns></returns> public Task SetPasswordHashAsync(UserInfo user, string passwordHash) { return Task.Run(() => { user.Password = passwordHash;//加密後 }); } /// <summary> /// 添加一個聲明 /// </summary> /// <param name="user"></param> /// <param name="claim"></param> /// <returns></returns> public Task AddClaimAsync(UserInfo user, System.Security.Claims.Claim claim) { return Task.Run(() => { Claims.Add(claim); }); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<IList<System.Security.Claims.Claim>> GetClaimsAsync(UserInfo user) { return Task.Run<IList<System.Security.Claims.Claim>>(() => { IList<System.Security.Claims.Claim> list = new List<System.Security.Claims.Claim>(); //聲明 //System.Security.Claims.Claim claimUserName = new System.Security.Claims.Claim("nick", user.UserName);//UserName //System.Security.Claims.Claim claimUserId = new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, user.Id.ToString());//UserId //list.Add(claimUserName); //list.Add(claimUserId); return list; }); } /// <summary> /// 移除聲明 /// </summary> /// <param name="user"></param> /// <param name="claim"></param> /// <returns></returns> public Task RemoveClaimAsync(UserInfo user, System.Security.Claims.Claim claim) { throw new NotImplementedException(); } /// <summary> /// 獲取訪問失敗次數 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> GetAccessFailedCountAsync(UserInfo user) { return Task.FromResult(1); } /// <summary> /// 獲取鎖定狀態 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetLockoutEnabledAsync(UserInfo user) { return Task<bool>.Run<bool>(() => { return false; }); } /// <summary> /// 獲取鎖定結束時間 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<DateTimeOffset> GetLockoutEndDateAsync(UserInfo user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> IncrementAccessFailedCountAsync(UserInfo user) { throw new NotImplementedException(); } /// <summary> /// 重置訪問時間計數 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task ResetAccessFailedCountAsync(UserInfo user) { return Task.FromResult(false); } #region LockOut /// <summary> /// 修改鎖定狀態 /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetLockoutEnabledAsync(UserInfo user, bool enabled) { return Task.Run(() => { }); } /// <summary> /// 設置鎖定時間 /// </summary> /// <param name="user"></param> /// <param name="lockoutEnd"></param> /// <returns></returns> public Task SetLockoutEndDateAsync(UserInfo user, DateTimeOffset lockoutEnd) { return Task.Run(() => { }); } #endregion #region Email /// <summary> /// 經過郵箱獲取用戶信息 /// </summary> /// <param name="email"></param> /// <returns></returns> public Task<UserInfo> FindByEmailAsync(string email) { return (new UserTask(null)).GetByEmail(email); } /// <summary> /// 獲取用戶郵箱 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetEmailAsync(UserInfo user) { return Task.Run(() => { return user.EMail; }); } /// <summary> /// 確認郵件 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetEmailConfirmedAsync(UserInfo user) { throw new NotImplementedException(); } /// <summary> /// 修改郵箱 /// </summary> /// <param name="user"></param> /// <param name="email"></param> /// <returns></returns> public Task SetEmailAsync(UserInfo user, string email) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetEmailConfirmedAsync(UserInfo user, bool confirmed) { throw new NotImplementedException(); } #endregion #region Phone /// <summary> /// 獲取手機號 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPhoneNumberAsync(UserInfo user) { return Task.Run(() => { return user.Mobile; }); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetPhoneNumberConfirmedAsync(UserInfo user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="phoneNumber"></param> /// <returns></returns> public Task SetPhoneNumberAsync(UserInfo user, string phoneNumber) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetPhoneNumberConfirmedAsync(UserInfo user, bool confirmed) { throw new NotImplementedException(); } #endregion /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetTwoFactorEnabledAsync(UserInfo user) { return Task.Run<bool>(() => { return false; }); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetTwoFactorEnabledAsync(UserInfo user, bool enabled) { return Task.Run(() => { }); } } }
這裏面還有不少功能還沒有實現,無論了,先放在那裏,等各位有時間再來實現吧。
數據調用能夠了,那麼還須要什麼呢?咱們還須要一個VonSignInManager類,這個類在Controller中有調用
咱們一樣創建在Models目錄中,VonSignInManager.cs
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin.Security; /****************************************************************************************************************** * 經過該類完成用戶基類 UserInfo(該類必須實現 Microsoft.AspNet.Identity.IUser<int>接口)向 Owin 的註冊,這樣全部的 * 認證 Owin 都會調用 PasswordSignInAsync 實現驗證和處理 * ***************************************************************************************************************/ namespace VonPortal.Web.Models { public class VonSignInManager : SignInManager<UserInfo, int> { /// <summary> /// 構造函數 /// </summary> /// <param name="UserManager"></param> /// <param name="AuthenticationManager"></param> public VonSignInManager(UserManager<UserInfo, int> UserManager, IAuthenticationManager AuthenticationManager) : base(UserManager, AuthenticationManager) { } /// <summary> /// 根據用戶名密碼,驗證用戶登陸 /// </summary> /// <param name="userName"></param> /// <param name="password"></param> /// <param name="isPersistent"></param> /// <param name="shouldLockout"></param> /// <returns></returns> public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout) { return base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout); } } }
這樣咱們就完成了全部代碼的擴展改造工做,咱們回頭再仔細研究一Controller這個類,研究下他是如何控制的。
if (string.IsNullOrEmpty(user.Email)) { return View(); } if (string.IsNullOrEmpty(user.Password)) { return View(); } //Context IOwinContext OwinContext = HttpContext.GetOwinContext(); //實例化UserStore對象 VonUserStore userStore = new VonUserStore(); //UserManager VonUserManager UserManager = new VonUserManager(userStore); //signInManager VonSignInManager signInManager = new VonSignInManager(UserManager, AutherticationManager); //登陸 SignInStatus SignInStatus = await signInManager.PasswordSignInAsync(user.Email, user.Password, true, shouldLockout: false);
首先作了一下信息驗證和校驗,而後就是建立了數據訪問對象
//實例化UserStore對象 VonUserStore userStore = new VonUserStore();
目的是爲了建立UserManager,同時完成UserManager和UserStore的綁定
//UserManager VonUserManager UserManager = new VonUserManager(userStore);
最後實SignInManager,一樣完成了UserManager的綁定。
//signInManager VonSignInManager signInManager = new VonSignInManager(UserManager, AutherticationManager);
這樣驗證所須要全部信息都整齊了,就直接調用Owin的PasswordSignInAsync(userName, password, isPersistent, shouldLockout);完成對用戶登陸信息的驗證。