关于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(基于声明)的认证
首先,这种机制并非微软特有的,Claims-based认证和授权在国外被广泛使用,包括微软的ADFS,Google,Facebook等。
Claims-based认证的主要特点:
- 将认证与授权拆分成独立的服务
- 服务调用者(一般是网站),不需要关注你如何去认证,你用Windows认证也好,用令牌手机短信也好,与我无关。
- 如果用户成功登录的话,认证服务(假如是QQ) 会返回给我们一个令牌。
- 令牌当中包含了服务调用者所需要的信息,用户名,以及角色信息等等。
接下来,我们会使用到两个对象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的配置工作。
如果你有更多疑问,不妨说出来,我们共同探讨。