关于AspNet.Identity,参考:http://www.cnblogs.com/shanyou/p/3918178.html
关于OWIN,可以阅读:http://www.cnblogs.com/dudu/p/what-is-owin.html
OWIN使ASP.NET应用运行在其它平台上称为可能。对ASP.NET程序和IIS进行解耦。我们可以在没有安装IIS的情况下,运行ASP.NET程序。在这里http://katanaproject.codeplex.com/可以下载源码。
另一个概念就是基于声明(Claim)的认证机制。
首先,这种机制并非微软特有的,Claims-based认证和授权在国外被广泛使用,包括微软的ADFS,Google,Facebook等。
Claims-based认证的主要特点:
接下来,我们会使用到两个对象Microsoft.AspNet.Identity.UserManager和Microsoft.AspNet.Identity.Owin.SignInManager,当然,在不使用Microsoft.AspNet.Identity.Owin.SignInManager的情况下,我们依然可以完成认证工作。在这里,我手动创建了两个类,分别集成前两个类。代码如下:
TiKuSignInManager 类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; /****************************************************************************************************************** * * * 说 明: (版本:Version1.0.0) * 作 者:李朝强 * 日 期:2015/05/19 * 修 改: * 参 考:http://my.oschina.net/lichaoqiang/ * 备 注:暂无... * * * ***************************************************************************************************************/ namespace AspNetIdentity.Models { public class TiKuSignInManager : Microsoft.AspNet.Identity.Owin.SignInManager<TiKuUser, Guid> { /// <summary> /// 构造函数 /// </summary> /// <param name="UserManager"></param> /// <param name="AuthenticationManager"></param> public TiKuSignInManager(Microsoft.AspNet.Identity.UserManager<TiKuUser, Guid> UserManager, Microsoft.Owin.Security.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 System.Threading.Tasks.Task<Microsoft.AspNet.Identity.Owin.SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout) { return base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout); } } }
TiKuUserManager 类:
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Web; namespace AspNetIdentity.Models { public class TiKuUserManager : Microsoft.AspNet.Identity.UserManager<TiKuUser, Guid> { /// <summary> /// 构造函数 /// </summary> /// <param name="store"></param> public TiKuUserManager(TiKuUserStore 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; } } } }这两个类,为我们提供了用户认证常用的方法。接下来,你在创建UserManager类的时候,发现,需要提供Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>类型对象来构造UserManager对象,于是我继承了这个Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>接口:
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 System.Web; /****************************************************************************************************************** * * * 说 明:TiKuUserStore (版本:Version1.0.0) * 作 者:李朝强 * 日 期:2015/05/19 * 修 改: * 参 考:http://my.oschina.net/lichaoqiang/ * 备 注:暂无... * IUserLockoutStore<User, TKey>: 在尝试一定的失败次数后允许锁定一个账号 IUserEmailStore<User, TKey>: 使用邮件地址做确认 (例如通过邮件进行确认) IUserPhoneNumberStore<User, TKey>: 使用手机号码做确认(例如通过短信进行确认) IUserTwoFactorStore<User, TKey>: 启用2中途径进行安全验证 (例如通过用户名/密码和通过邮件或者短信的令牌),当用户密码可能存在不安全隐患的时候,系统会以短信或邮件的方式向用户发送安全码 * * ***************************************************************************************************************/ namespace AspNetIdentity.Models { public class TiKuUserStore : Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>, IUserPasswordStore<TiKuUser, Guid>, IUserClaimStore<TiKuUser, Guid>, IUserLockoutStore<TiKuUser, Guid>, IUserEmailStore<TiKuUser, Guid>, IUserPhoneNumberStore<TiKuUser, Guid>, IUserTwoFactorStore<TiKuUser, Guid> { /// <summary> /// 声明 /// </summary> public IList<System.Security.Claims.Claim> Claims = null; /// <summary> /// 实例化 /// </summary> public TiKuUserStore() { //声明 Claims = new List<System.Security.Claims.Claim>(); } /// <summary> /// 用户 /// </summary> public TiKuUser UserIdentity = null; /// <summary> /// 创建用户 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task CreateAsync(TiKuUser user) { return Task.Run(() => { string strInsertCmd = @"INSERT INTO[tb_User](ID,UserName,UserPwd) VALUES(@UserID,@UserName,@UserPwd);"; SqlParameter[] parameters = { new SqlParameter("@UserName",SqlDbType.NVarChar,30), new SqlParameter("@UserPwd",SqlDbType.NVarChar,100), new SqlParameter("@UserID",SqlDbType.UniqueIdentifier) }; parameters[0].Value = user.UserName; parameters[1].Value = user.Password; parameters[2].Value = user.Id; int iResult = DbHelper.ExecuteNonQuery(strInsertCmd, parameters); }); } /// <summary> /// 删除用户 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task DeleteAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 2>通过用户ID,获取用户 /// </summary> /// <param name="userId"></param> /// <returns></returns> public System.Threading.Tasks.Task<TiKuUser> FindByIdAsync(Guid userId) { return Task<TiKuUser>.Run<TiKuUser>(() => { if (UserIdentity != null) { return UserIdentity; } string strCmd = "SELECT * FROM [tb_User] WHERE ID=@UserID;"; SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.UniqueIdentifier) }; parameters[0].Value = userId; List<TiKuUser> list = new List<TiKuUser>(); using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters)) { while (data.Read()) { //model TiKuUser user = new TiKuUser(); user.Id = Guid.Parse(data["ID"].ToString()); user.UserName = data["UserName"].ToString(); user.Password = data["UserPwd"].ToString(); list.Add(user); } } UserIdentity = list.FirstOrDefault(); return UserIdentity; }); } /// <summary> /// 1>通过用户名获取用户信息 /// </summary> /// <param name="userName"></param> /// <returns></returns> public System.Threading.Tasks.Task<TiKuUser> FindByNameAsync(string userName) { return Task<TiKuUser>.Run<TiKuUser>(() => { if (UserIdentity != null) { return UserIdentity; } string strCmd = "SELECT * FROM [tb_User] WHERE UserName=@UserName;"; SqlParameter[] parameters = { new SqlParameter("@UserName", SqlDbType.NVarChar, 30) }; parameters[0].Value = userName; List<TiKuUser> list = new List<TiKuUser>(); using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters)) { while (data.Read()) { //model TiKuUser user = new TiKuUser(); user.Id = Guid.Parse(data["ID"].ToString()); user.UserName = data["UserName"].ToString(); user.Password = data["UserPwd"].ToString(); list.Add(user); } } //模拟数据库 UserIdentity = list.FirstOrDefault(); return UserIdentity; }); } /// <summary> /// 更新用户信息 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task UpdateAsync(TiKuUser user) { return Task.Run(() => { }); } /// <summary> /// 释放 /// </summary> public void Dispose() { throw new NotImplementedException(); } /// <summary> /// 获取密码 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPasswordHashAsync(TiKuUser user) { return Task<string>.Run(() => { return user.Password; }); } /// <summary> /// 是否有密码 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> HasPasswordAsync(TiKuUser user) { return Task.FromResult<bool>(!string.IsNullOrEmpty(user.Password)); } /// <summary> /// 密码进行加密 /// </summary> /// <param name="user"></param> /// <param name="passwordHash"></param> /// <returns></returns> public Task SetPasswordHashAsync(TiKuUser user, string passwordHash) { return Task.Run(() => { user.Password = passwordHash;//加密后 }); } /// <summary> /// 添加一个声明 /// </summary> /// <param name="user"></param> /// <param name="claim"></param> /// <returns></returns> public Task AddClaimAsync(TiKuUser 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(TiKuUser 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(TiKuUser user, System.Security.Claims.Claim claim) { throw new NotImplementedException(); } /// <summary> /// 获取访问失败次数 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> GetAccessFailedCountAsync(TiKuUser user) { return Task<Int32>.FromResult<Int32>(1); } /// <summary> /// 获取锁定状态 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetLockoutEnabledAsync(TiKuUser user) { return Task<bool>.Run<bool>(() => { return false; }); } /// <summary> /// 获取锁定结束时间 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<DateTimeOffset> GetLockoutEndDateAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> IncrementAccessFailedCountAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 重置访问时间计数 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task ResetAccessFailedCountAsync(TiKuUser user) { return Task.FromResult(false); } #region LockOut /// <summary> /// 修改锁定状态 /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetLockoutEnabledAsync(TiKuUser user, bool enabled) { return Task.Run(() => { }); } /// <summary> /// 设置锁定时间 /// </summary> /// <param name="user"></param> /// <param name="lockoutEnd"></param> /// <returns></returns> public Task SetLockoutEndDateAsync(TiKuUser user, DateTimeOffset lockoutEnd) { return Task.Run(() => { }); } #endregion #region Email /// <summary> /// 通过邮箱获取用户信息 /// </summary> /// <param name="email"></param> /// <returns></returns> public Task<TiKuUser> FindByEmailAsync(string email) { throw new NotImplementedException(); } /// <summary> /// 获取用户邮箱 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetEmailAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 确认邮件 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetEmailConfirmedAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 修改邮箱 /// </summary> /// <param name="user"></param> /// <param name="email"></param> /// <returns></returns> public Task SetEmailAsync(TiKuUser user, string email) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetEmailConfirmedAsync(TiKuUser user, bool confirmed) { throw new NotImplementedException(); } #endregion #region Phone /// <summary> /// 获取手机号 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPhoneNumberAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetPhoneNumberConfirmedAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="phoneNumber"></param> /// <returns></returns> public Task SetPhoneNumberAsync(TiKuUser user, string phoneNumber) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetPhoneNumberConfirmedAsync(TiKuUser user, bool confirmed) { throw new NotImplementedException(); } #endregion /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetTwoFactorEnabledAsync(TiKuUser user) { return Task.Run<bool>(() => { return false; }); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetTwoFactorEnabledAsync(TiKuUser user, bool enabled) { return Task.Run(() => { }); } } }下面,我们看看注册方法该怎么写,在这里,我用MVC5作为代码示例,在解决方案中,创建AccountController控制器:
[Authorize] public class AccountController : Controller { /// <summary> ///注册:这里省事,没有写UI /// </summary> /// <param name="user"></param> /// <returns></returns> [AllowAnonymous] public async Task<ActionResult> Register() { //user TiKuUser user = new TiKuUser { Id = Guid.NewGuid(), UserName = "chaoqiangli", Password = "XXXX" }; //Context Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext(); //用户储存 Models.TiKuUserStore userStore = new Models.TiKuUserStore(); //UserManager TiKuUserManager UserManager = new TiKuUserManager(userStore); IdentityResult result = await UserManager.CreateAsync(user, user.Password); if (result.Succeeded) { Response.Write("注册成功!"); } return View(); } }
我们来看看,Models.TiKuUserStore 对象都完成了那些工作。
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 System.Web; /****************************************************************************************************************** * * * 说 明:TiKuUserStore (版本:Version1.0.0) * 作 者:李朝强 * 日 期:2015/05/19 * 修 改: * 参 考:http://my.oschina.net/lichaoqiang/ * 备 注:暂无... * IUserLockoutStore<User, TKey>: 在尝试一定的失败次数后允许锁定一个账号 IUserEmailStore<User, TKey>: 使用邮件地址做确认 (例如通过邮件进行确认) IUserPhoneNumberStore<User, TKey>: 使用手机号码做确认(例如通过短信进行确认) IUserTwoFactorStore<User, TKey>: 启用2中途径进行安全验证 (例如通过用户名/密码和通过邮件或者短信的令牌),当用户密码可能存在不安全隐患的时候,系统会以短信或邮件的方式向用户发送安全码 * * ***************************************************************************************************************/ namespace AspNetIdentity.Models { public class TiKuUserStore : Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>, IUserPasswordStore<TiKuUser, Guid>, IUserClaimStore<TiKuUser, Guid>, IUserLockoutStore<TiKuUser, Guid>, IUserEmailStore<TiKuUser, Guid>, IUserPhoneNumberStore<TiKuUser, Guid>, IUserTwoFactorStore<TiKuUser, Guid> { /// <summary> /// 声明 /// </summary> public IList<System.Security.Claims.Claim> Claims = null; /// <summary> /// 实例化 /// </summary> public TiKuUserStore() { //声明 Claims = new List<System.Security.Claims.Claim>(); } /// <summary> /// 用户 /// </summary> public TiKuUser UserIdentity = null; /// <summary> /// 创建用户 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task CreateAsync(TiKuUser user) { return Task.Run(() => { string strInsertCmd = @"INSERT INTO[tb_User](ID,UserName,UserPwd) VALUES(@UserID,@UserName,@UserPwd);"; SqlParameter[] parameters = { new SqlParameter("@UserName",SqlDbType.NVarChar,30), new SqlParameter("@UserPwd",SqlDbType.NVarChar,100), new SqlParameter("@UserID",SqlDbType.UniqueIdentifier) }; parameters[0].Value = user.UserName; parameters[1].Value = user.Password; parameters[2].Value = user.Id; int iResult = DbHelper.ExecuteNonQuery(strInsertCmd, parameters); }); } /// <summary> /// 删除用户 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task DeleteAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 2>通过用户ID,获取用户 /// </summary> /// <param name="userId"></param> /// <returns></returns> public System.Threading.Tasks.Task<TiKuUser> FindByIdAsync(Guid userId) { return Task<TiKuUser>.Run<TiKuUser>(() => { if (UserIdentity != null) { return UserIdentity; } string strCmd = "SELECT * FROM [tb_User] WHERE ID=@UserID;"; SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.UniqueIdentifier) }; parameters[0].Value = userId; List<TiKuUser> list = new List<TiKuUser>(); using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters)) { while (data.Read()) { //model TiKuUser user = new TiKuUser(); user.Id = Guid.Parse(data["ID"].ToString()); user.UserName = data["UserName"].ToString(); user.Password = data["UserPwd"].ToString(); list.Add(user); } } UserIdentity = list.FirstOrDefault(); return UserIdentity; }); } /// <summary> /// 1>通过用户名获取用户信息 /// </summary> /// <param name="userName"></param> /// <returns></returns> public System.Threading.Tasks.Task<TiKuUser> FindByNameAsync(string userName) { return Task<TiKuUser>.Run<TiKuUser>(() => { if (UserIdentity != null) { return UserIdentity; } string strCmd = "SELECT * FROM [tb_User] WHERE UserName=@UserName;"; SqlParameter[] parameters = { new SqlParameter("@UserName", SqlDbType.NVarChar, 30) }; parameters[0].Value = userName; List<TiKuUser> list = new List<TiKuUser>(); using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters)) { while (data.Read()) { //model TiKuUser user = new TiKuUser(); user.Id = Guid.Parse(data["ID"].ToString()); user.UserName = data["UserName"].ToString(); user.Password = data["UserPwd"].ToString(); list.Add(user); } } //模拟数据库 UserIdentity = list.FirstOrDefault(); return UserIdentity; }); } /// <summary> /// 更新用户信息 /// </summary> /// <param name="user"></param> /// <returns></returns> public System.Threading.Tasks.Task UpdateAsync(TiKuUser user) { return Task.Run(() => { }); } /// <summary> /// 释放 /// </summary> public void Dispose() { throw new NotImplementedException(); } /// <summary> /// 获取密码 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPasswordHashAsync(TiKuUser user) { return Task<string>.Run(() => { return user.Password; }); } /// <summary> /// 是否有密码 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> HasPasswordAsync(TiKuUser user) { return Task.FromResult<bool>(!string.IsNullOrEmpty(user.Password)); } /// <summary> /// 密码进行加密 /// </summary> /// <param name="user"></param> /// <param name="passwordHash"></param> /// <returns></returns> public Task SetPasswordHashAsync(TiKuUser user, string passwordHash) { return Task.Run(() => { user.Password = passwordHash;//加密后 }); } /// <summary> /// 添加一个声明 /// </summary> /// <param name="user"></param> /// <param name="claim"></param> /// <returns></returns> public Task AddClaimAsync(TiKuUser 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(TiKuUser 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(TiKuUser user, System.Security.Claims.Claim claim) { throw new NotImplementedException(); } /// <summary> /// 获取访问失败次数 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> GetAccessFailedCountAsync(TiKuUser user) { return Task<Int32>.FromResult<Int32>(1); } /// <summary> /// 获取锁定状态 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetLockoutEnabledAsync(TiKuUser user) { return Task<bool>.Run<bool>(() => { return false; }); } /// <summary> /// 获取锁定结束时间 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<DateTimeOffset> GetLockoutEndDateAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<int> IncrementAccessFailedCountAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 重置访问时间计数 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task ResetAccessFailedCountAsync(TiKuUser user) { return Task.FromResult(false); } #region LockOut /// <summary> /// 修改锁定状态 /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetLockoutEnabledAsync(TiKuUser user, bool enabled) { return Task.Run(() => { }); } /// <summary> /// 设置锁定时间 /// </summary> /// <param name="user"></param> /// <param name="lockoutEnd"></param> /// <returns></returns> public Task SetLockoutEndDateAsync(TiKuUser user, DateTimeOffset lockoutEnd) { return Task.Run(() => { }); } #endregion #region Email /// <summary> /// 通过邮箱获取用户信息 /// </summary> /// <param name="email"></param> /// <returns></returns> public Task<TiKuUser> FindByEmailAsync(string email) { throw new NotImplementedException(); } /// <summary> /// 获取用户邮箱 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetEmailAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 确认邮件 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetEmailConfirmedAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// 修改邮箱 /// </summary> /// <param name="user"></param> /// <param name="email"></param> /// <returns></returns> public Task SetEmailAsync(TiKuUser user, string email) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetEmailConfirmedAsync(TiKuUser user, bool confirmed) { throw new NotImplementedException(); } #endregion #region Phone /// <summary> /// 获取手机号 /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<string> GetPhoneNumberAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetPhoneNumberConfirmedAsync(TiKuUser user) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="phoneNumber"></param> /// <returns></returns> public Task SetPhoneNumberAsync(TiKuUser user, string phoneNumber) { throw new NotImplementedException(); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="confirmed"></param> /// <returns></returns> public Task SetPhoneNumberConfirmedAsync(TiKuUser user, bool confirmed) { throw new NotImplementedException(); } #endregion /// <summary> /// /// </summary> /// <param name="user"></param> /// <returns></returns> public Task<bool> GetTwoFactorEnabledAsync(TiKuUser user) { return Task.Run<bool>(() => { return false; }); } /// <summary> /// /// </summary> /// <param name="user"></param> /// <param name="enabled"></param> /// <returns></returns> public Task SetTwoFactorEnabledAsync(TiKuUser user, bool enabled) { return Task.Run(() => { }); } } }现在,我们可以编写用户注册的方法了,这是,我们会用到另一个对象,TiKuUser,它继承自Microsoft.AspNet.Identity.IUser<Guid>接口,根据实际情况,我们可以去拓展它。
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Web; namespace AspNetIdentity.Models { public class TiKuUser : Microsoft.AspNet.Identity.IUser<Guid> { /// <summary> /// 用户编号 /// </summary> public Guid Id { get; set; } /// <summary> /// /// </summary> [DisplayName("登录名")] public string UserName { get; set; } /// <summary> /// 密码 /// </summary> [DisplayName("密码")] public string Password { get; set; } /// <summary> /// 昵称 /// </summary> [DisplayName("昵称")] public string Nick { get; set; } } }这样,就完成了用户的注册。接下来,就是用户认证的过程了。这时,你会发现,Microsoft.AspNet.Identity.Owin.SignInManager为我们提供了丰富的方法,来完成用户的认证。认证成功后,会向客户端发送加密的Cookie。这时,我们可通过HttpContext.Current.User对象,来获取认证信息。
登录代码如下:
/// <summary> /// 登陆 /// </summary> /// <param name="user"></param> /// <returns></returns> [HttpPost] [AllowAnonymous] public async Task<ActionResult> Login(TiKuUser @user) { if (string.IsNullOrEmpty(@user.UserName)) { return View(); } if (string.IsNullOrEmpty(@user.Password)) { return View(); } //Context Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext(); //实例化UserStore对象 Models.TiKuUserStore userStore = new Models.TiKuUserStore(); //UserManager TiKuUserManager UserManager = new TiKuUserManager(userStore); //signInManager TiKuSignInManager signInManager = new TiKuSignInManager(UserManager, AutherticationManager); //登录 Microsoft.AspNet.Identity.Owin.SignInStatus SignInStatus = await signInManager.PasswordSignInAsync(@user.UserName, @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); } }我们来看看实际效果吧。
这里,做了个简单的登录表单。登录成功后,会发现,客户端多了一长串Cookie。
这是加密后的用户登录凭据。这样,用户认证成功后,就可以访问到[Authorize]的Action了。
我们在创建MVC项目的时候,有两个文件需要注意下,就是根目录下的Startup.cs和App_Start目录下的Startup.Auth.cs两个类,它们以分布类的形式,存放于解决方案不同目录中。我们看看Startup都做了那些工作。
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; /****************************************************************************************************************** * * * 说 明: Startup(版本:Version1.0.0) * 作 者:李朝强 * 日 期:2015/05/19 * 修 改: * 参 考:http://my.oschina.net/lichaoqiang/ * 备 注:暂无... * * * ***************************************************************************************************************/ [assembly: OwinStartup(typeof(AspNetIdentity.Startup))] namespace AspNetIdentity { public partial class Startup { /// <summary> /// 配置 /// </summary> /// <param name="app"></param> public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888 ConfigureAuth(app); } } } using Microsoft.AspNet.Identity; using Microsoft.Owin; using Microsoft.Owin.Security.Cookies; using Owin; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace AspNetIdentity { 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 = "__KaoLaTicketSid" }); // Use a cookie to temporarily store information about a user logging in with a third party login provider app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); } } }
有了这个两个启动类,应用程序在启动的时候,就会触发Configuration方法,完成OWIN的配置工作。
如果你有更多疑问,不妨说出来,我们共同探讨。