Microsoft.AspNet.Identity 自定义使用现有的表—登录实现
Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现。Microsoft.AspNet.Identity.EntityFramework则是Microsoft.AspNet.Identity的数据提供实现。但是在使用此框架的时候存在一些问题,如果是全新的项目还可以使用它默认提供的表名,字段名等。但是如果是在一些老的数据库上应用这个框架就比较麻烦了。所以我们实现一个自己的Microsoft.AspNet.Identity.EntityFramework
首先我们只说登录,登录的入口代码是
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
对应Owin框架中的代码为
public virtual async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
SignInStatus result;
if (this.UserManager == null)
{
result = SignInStatus.Failure;
}
else
{
TUser tUser = await this.UserManager.FindByNameAsync(userName).WithCurrentCulture<TUser>();
if (tUser == null)
{
result = SignInStatus.Failure;
}
else if (await this.UserManager.IsLockedOutAsync(tUser.Id).WithCurrentCulture<bool>())
{
result = SignInStatus.LockedOut;
}
else if (await this.UserManager.CheckPasswordAsync(tUser, password).WithCurrentCulture<bool>())
{
await this.UserManager.ResetAccessFailedCountAsync(tUser.Id).WithCurrentCulture<IdentityResult>();
result = await this.SignInOrTwoFactor(tUser, isPersistent).WithCurrentCulture<SignInStatus>();
}
else
{
if (shouldLockout)
{
await this.UserManager.AccessFailedAsync(tUser.Id).WithCurrentCulture<IdentityResult>();
if (await this.UserManager.IsLockedOutAsync(tUser.Id).WithCurrentCulture<bool>())
{
result = SignInStatus.LockedOut;
return result;
}
}
result = SignInStatus.Failure;
}
}
return result;
}
由此代码可大概知晓登录的流程是,当然还有登录失败的流程就先不实现了。需要实现也非常简单,根据Owin的源代码实现对应的接口即可.
1.FindByNameAsync 先根据登录名找到user对象,使用UserManager中的UserStroe所实现IUserStore的接口方法
2.IsLockedOutAsync 检查登录是否锁定,使用UserManager中的UserStroe所实现的IUserLockoutStore接口方法
3.CheckPasswordAsync 检查密码,使用UserManager中的UserStroe所实现的IUserPasswordStore接口方法
4.ResetAccessFailedCountAsync 登录成功,重置登录失败计数,使用UserManager中的UserStroe所实现的IUserLockoutStore接口方法
5.SignInOrTwoFactor 双重身份验证,使用UserManager中的UserStroe所实现的IUserTwoFactorStore接口方法
SignInManager是入口,需要用到UserManager,UserManager需要用到关键的UserStore,具体的框架的介绍可以参考园子里其他的文章,都讲的很好,并且很好的讲明了为何需要这么设计。
实现
已有资源,假如我们已经有了数据库,有了user表,有了id字段guid类型,有了loginid代表登录的用户名,也就是源代码中的username
第一步 先实现我们自己的SignInManager,继承自Microsoft.AspNet.Identity.Owin.SignInManager<TUser, TKey>
public class WXSignInManager : SignInManager<WXUser, Guid>
{
public WXSignInManager(UserManager<WXUser, Guid> userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager)
{
}
public static WXSignInManager Create(IdentityFactoryOptions<WXSignInManager> options, IOwinContext context)
{
return new WXSignInManager(context.GetUserManager<WXUserManager>(), context.Authentication);
}
我们的SignInManager代码中有一行context.GetUserManager<WXUserManager>(),所以继续实现我们的UserManager。
第二步 实现我们的自己的UserManager,继承自Microsoft.AspNet.Identity.UserManager<TUser, TKey>
public class WXUserManager : UserManager<WXUser, Guid>
{
public WXUserManager(IUserStore<WXUser, Guid> store) : base(store)
{
} public static WXUserManager Create(IdentityFactoryOptions<WXUserManager> options, IOwinContext context)
{
return new WXUserManager(new WXUserStore(context.Get<WXDBContexnt>()))
{
PasswordHasher = new MyPasswordHasher()
};
}
}
由之前Owin源代码可以知道重点代码都在UserStore中,接下来
第三步,实现我们自己的UserStore,分别实现接口
Microsoft.AspNet.Identity.IUserStore<TUser, in TKey>,//数据库访问相关接口
Microsoft.AspNet.Identity.IUserLockoutStore<TUser, in TKey>,//用户锁定,登录失败计数相关接口
Microsoft.AspNet.Identity.IUserPasswordStore<TUser, in TKey>,//用户密码相关接口
Microsoft.AspNet.Identity,IUserTwoFactorStore<TUser, in TKey>//双重身份验证相关接口
public class WXUserStore : IUserStore<WXUser, Guid>, IUserLockoutStore<WXUser, Guid>, IUserPasswordStore<WXUser, Guid>, IUserTwoFactorStore<WXUser, Guid>
{
public WXUserStore(WXDBContexnt dbContext)
{
this.dbContext = dbContext;
}
WXDBContexnt dbContext; public async Task<WXUser> FindByIdAsync(Guid userId)
{
var user = await dbContext.WXUser.FindAsync(userId);
return user;
} public async Task<WXUser> FindByNameAsync(string userName)
{
return dbContext.WXUser.Where(p => p.LoginId == userName).FirstOrDefaultAsync();
}
public Task ResetAccessFailedCountAsync(WXUser user)
{
return Task.FromResult(false);
}
public Task<bool> GetLockoutEnabledAsync(WXUser user)
{
return Task.FromResult(false);
}
public Task<string> GetPasswordHashAsync(WXUser user)
{
return Task.FromResult(user.LoginPWD);
}
public Task<bool> GetTwoFactorEnabledAsync(WXUser user)
{
return Task.FromResult(false);
}
}
这里仅仅是完成一个超级简单的登录功能,所以无关的实现都删除了,需要注意的是p => p.LoginId == userName,原有数据库中登录名的字段是loginId。接口的意思可以查看文档即可,相信从方法的名字就能猜到具体的意思,人家设计的接口就是好<!_!>。
我这里使用的是EF作为数据提供源,当然你也可以使用自己的,只需要替换FindByIdAsync,FindByNameAsync方法中对应的实现,哪怕是在这些方面里面使用ado.net直接查询数据都是完全没有问题的。wxuser我继承了系统已经存在的user对象,然后强类型实现了IUser接口,因为我原系统对象已存在了username属性。而此处的wxuser.username属性是作为用户登录的账号意思存在的。所以我强类型实现。
public class WXUser : 系统已存在的user entity对象, IUser<Guid>
{
Guid IUser<Guid>.Id
{
get
{
return this.Id;
}
} string IUser<Guid>.UserName
{
get
{
return this.LoginId;
} set
{
this.LoginId = value;
}
}
} public class WXDBContexnt : DbContext
{
public WXDBContexnt()
{ }
public static WXDBContexnt Create() { return new WXDBContexnt(); }
public DbSet<WXUser> WXUser { get; set; }
}
大致代码就是如此了,当然我们自己实现的UserStore对象还有很多方法没有实现,but我只是需要一个登录不是么,可以慢慢改造的嘛<!_!>
写到最后想到通过重写的方式估计也能实现,这是新建项目生成的默认代码,为什么不可以增加[Table("Users")],[Column("LoginId")],override达到效果呢。
[Table("Users")]
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// 在此处添加自定义用户声明
return userIdentity;
}
[Column("LoginId")]
public override string UserName
{
get
{
return base.UserName;
}
set
{
base.UserName = value;
}
}
}
PS:看过源代码了,标记方式针对表名不行,源代码中写死了table name。字段名可以通过标记方式重命名 --by 2016-10-24
Microsoft.AspNet.Identity 自定义使用现有的表—登录实现的更多相关文章
- Microsoft.AspNet.Identity 自定义使用现有的表—登录实现,aspnet.identity
Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...
- Asp.net Identity 系列之 怎样修改Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的 Id 字段的数据类型
这篇博客我们来学习如何将AspNetUsers 表的Id 字段 的类型由nvarchar(128) 改为Int 并且子增长 1.为什么要修改 如果你运行过 Asp.net mvc 示例项目,你好会发现 ...
- 跟Microsoft.AspNet.Identity学习哈希加盐法
什么是哈希加盐法? 废话少说:对于MD5这种加密算法,同样的密码每次加密后得到的密文是一样的,所以黑客可以利用已知的密码库(彩虹库)对目标数据库密文进行对比进行攻击. 怎样解决:哈希加盐法,以下是网上 ...
- 从Microsoft.AspNet.Identity看微软推荐的一种MVC的分层架构
Microsoft.AspNet.Identity简介 Microsoft.AspNet.Identity是微软在MVC 5.0中新引入的一种membership框架,和之前ASP.NET传统的mem ...
- Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; ...
- Microsoft.AspNet.Identity 的简单使用
要完成一个简单的注册,登陆,至少需要实现Identity中的3个接口 IUser IUserStore<TUser> : IDisposable where TUser : IUser I ...
- MVC5中 在更新 Microsoft.Aspnet.Identity 后编译器错误
环境:vs2013预览版chs,我试着创建vb.net web应用,从对话框中选择MVC和WebAPI.编译ok了.通过NuGet管理器更新了Microsoft.Aspnet.Identity.Cor ...
- Microsoft.AspNet.Identity: UserID用整型数据表示, 而不是GUID
第一篇: 这个好像不太好 http://stackoverflow.com/questions/19553424/how-to-change-type-of-id-in-microsoft-aspn ...
- Microsoft.AspNet.Identity 重置密码
重置密码:先生成重置密码的Token,然后调用ResetPassword方法重置密码,密码要符合规则.. ApplicationUserManager UserManager => _userM ...
随机推荐
- Android UI ListView的使用
一.ListView的理解 1.什么ListView? 一种用来显示多个可滑动项(Item)列表的的ViewGroup 需要使用Adapter将集合数据和每一个Item所对应的布局动态适配到Li ...
- jQuery对表单的操作
表单应用 一个表单有3个基本组成部分: 表单标签:包含处理表单数据所用的服务器端程序URL以及数据提交到服务器的方法 表单域:包含文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上 ...
- Ignite China 2015 之行
微软首届Ignite China选择了金秋十月的北京,在顺义的九华山庄举办.这几天北京的空气特别好,再加上郊区高楼少,令人心胸开阔了不少.这次Ignite之行的任务有两个,其一是27号晚上与Windo ...
- C#调用C/C++动态库 封送结构体,结构体数组
一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...
- DB监控-redis监控
公司的redis业务很多,redis监控自然也是DB监控的一大模块,包括采集.展示.监控告警.本文主要介绍redis监控的主要指标和采集方法. 一.Redis监控系统逻辑 1.DBA通过前台页面添加r ...
- 云计算与 OpenStack - 每天5分钟玩转 OpenStack(14)
“云计算” 算是近年来最热的词了.现在 IT 行业见面不说这三个字您都不好意思跟人家打招呼. 对于云计算,学术界有各种定义,大家有兴趣可以百度一下. CloudMan 这里主要想从技术的角度谈谈对云计 ...
- Source Insight常用功能设置
熟悉工具的使用能在一定程度上提高工作效率,但工具永远只是工具,大家要把重点放在内功的修炼上. 符号导航 符号(变量.宏定义.结构定义.枚举.函数等等)在SI 中的检索非常方便.Ctrl+鼠标左键或Ct ...
- mysqld设置密码
用root 进入mysql后 mysql>set password =password('你的密码'); mysql>flush privileges; 登录: mysql -u ro ...
- redis 查看的版本
linux环境下查看redis的版本: 查看redis的版本有两种方式:1. redis-server --version 和 redis-server -v 得到的结果是:Redis server ...
- linux mail利用外部邮箱地址发邮件
mail命令发送邮件需要sendmail或postfix服务 三种常用格式发信 mail -s "标题" xxx@xxx.xxx #第一种方法,你可以把当前shell当成编辑器来用 ...