首先是建立启动单元:App_Start目录中的Startup.Auth.cs
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); } } }
建立用户用户信息结构:
#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的机制来一步一步的实现认证功能了
先写一个页面功能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建立的工程,都会有的
@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.cs
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)》