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;
}
}
}

Microsoft.AspNet.Identity 自定义使用现有的表—登录实现,aspnet.identity的更多相关文章

  1. Microsoft.AspNet.Identity 自定义使用现有的表—登录实现

    Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...

  2. MVC6 OWin Microsoft Identity 自定义验证

    1. Startup.cs中修改默认的验证设置 //app.UseIdentity(); app.UseCookieAuthentication(options => { //options.A ...

  3. ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core

    前言 原本本节内容是不存在的,出于有几个人问到了我:我想使用ASP.NET Core Identity,但是我又不想使用默认生成的数据库表,想自定义一套,我想要使用ASP.NE Core Identi ...

  4. 【FBA】SharePoint 2013自定义Providers在基于表单的身份验证(Forms-Based-Authentication)中的应用

    //http://www.cnblogs.com/OceanEyes/p/custom-provider-in-sharepoint-2013-fba-authentication.html 由于项目 ...

  5. [FBA]SharePoint 2013自定义Providers在基于表单的身份验证(Forms-Based-Authentication)中的应用

    //http://tech.ddvip.com/2014-05/1401197453210723.html 由于项目的需要,登录SharePoint Application的用户将从一个统一平台中获取 ...

  6. SharePoint 2013自定义Providers在基于表单的身份验证(Forms-Based-Authentication)中的应用

    由于项目的需要,登录SharePoint Application的用户将从一个统一平台中获取,而不是从Domain中获取,所以需要对SharePoint Application的身份验证(Claims ...

  7. 一起学微软Power BI系列-使用技巧(5)自定义PowerBI时间日期表

    1.日期函数表作用 经常使用Excel或者PowerBI,Power Pivot做报表,时间日期是一个重要的纬度,加上做一些钻取,时间日期函数表不可避免.所以今天就给大家分享一个自定义的做日期表的方法 ...

  8. python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API

    python  Django教程  之 模型(数据库).自定义Field.数据表更改.QuerySet API 一.Django 模型(数据库) Django 模型是与数据库相关的,与数据库相关的代码 ...

  9. django 多对多自定义第三张表时的注意事项

    杂交(自定义第三张表+ManyToManyField) # modles.py class Boy(models.Model): name = models.CharField(max_length= ...

随机推荐

  1. 在GitHub上使用Hexo 搭建自己的博客

    1.下载Node.js安装文件(现在电脑基本都是64位的,我就放64位的下载地址):https://nodejs.org/dist/v8.9.4/node-v8.9.4-x64.msi 或者自行到官网 ...

  2. mysql 组合聚集函数

    mysql> select * from table1; +----------+------------+-----+---------------------+ | name_new | t ...

  3. D3.js的v5版本入门教程(第七章)—— 比例尺的使用

    D3.js的v5版本入门教程(第七章) 比例尺在D3.js中是一个很重要的东西,我们可以这样理解d3.js中的比例尺——一种映射关系,从domain映射到range域(为什么会是domain和rang ...

  4. 分享一些好用的 Chrome 扩展

    阅读本文大概需要 2.8 分钟. 前言 使用浏览器扩展程序可以使你的工作效率提高数倍不止,那么下面我就向大家分享一下我日常使用的扩展,可能大多数扩展大家都已经在使用了,不过也难免有一两个是你不知道的. ...

  5. AOP通知类型

    AOP通知类型 前置通知 在目标方法执行之前进行操作 后置通知 在目标方法执行之后 进行操作 环绕通知 在目标方法执行之前 和之后进行操作 public Object arount() 异常抛出通知 ...

  6. 导入eclipse有Unbound classpath variable: 'M2_REPO报错的解决方法

    Eclipse maven of the project reported in Unbound classpath variable: 'M2_REPO /**/***/***. jar' But ...

  7. Python3教程—很经典可以快速上手

    原文地址:https://www.runoob.com/python3/python3-tutorial.html Python 3 教程 Python 的 3.0 版本,常被称为 Python 30 ...

  8. linux列出当前目录下的所有的目录?

    ###  列出当前目录下的所有目录: [root@localhost ~]# ls -ld * #列出所有的文件 drwxr-xr-x. root root Nov : elasticsearch d ...

  9. Qt编写小清新风格界面

    给一个朋友定制的界面,左侧有导航,左侧底部有运行+暂停+停止按钮,右侧有可伸缩面板,面板之间可以拉伸调节高度,左右两侧可以拉伸调节高度,所有的宽高和位置都保存在配置文件,下次重启立即应用,无边框标题栏 ...

  10. 报错:ImportError: cannot import name "KafkaProducer" from "kafka"

    报错背景: 在Pycharm中安装完成kafka-python之后,我开始在代码中引入kafka的包. from kafka import KafkaProducer 但是引入之后报错 报错现象: 报 ...