OWIN實現MVC5 的系統登陸

aspnetidentity

首先是創建啓動單元: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);完成對用戶登陸信息的驗證。

本文參照 李朝強 OWIN+AspNet.Identity實現用戶認證/登陸/註冊(MVC)

相關文章
相關標籤/搜索