ASP.NET Identity

ASP.NET Identity

基础示例

  ASP.NET Identity是在.NET Framework4.5中引入的,从Membership发布以来,我想微软已经从开发者以及企业客户那里面得到了足够的反馈信息来帮助他们打造这样一套新的框架。他所拥有的特点大多也是前面所不能满足的,至少我们看到的是进步,不是么?

  1. 一套ASP.NET Identity,可以用于ASP.NET下的web form, MVC, web pages, web API等
  2. 和Simple Membership Provider,可以灵活订制用户信息,同样采用EF Code First来完成数据操作
  3. 完全自定义数据结构
  4. 单元测试的支持
  5. 与Role Provider集成 
  6. 支持面向Clamis的认证
  7. 支持社交账号的登录
  8. OWIN 集成
  9. 通过NuGet发布来实现快速迭代

  瞟一眼好处还真不少,但是至少对于开发者来说,好用,能满足需求,灵活才是王道,那我们下面就来看看如何使用ASP.NET Identity来完成我们的用户授权和认证模块。其实我们已经不用写任何示例代码,因为我们只要使用VS创建一个.NET Framework 4.5 的 MVC站点,所有的代码都已经包括了。

默认创建的IdentityModels.cs

public class ApplicationUser : IdentityUser
{    }
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }
}

  

我们需要在ApplicaitonUser实体中添加我们的用户字段就可以了,同时我们还可以很简单的更改表名。

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection"){}
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
 
        // 默认表名是AspNetUsers,我们可以把它改成任意我们想要的
        modelBuilder.Entity<IdentityUser>()
            .ToTable("Users");
        modelBuilder.Entity<ApplicationUser>()
            .ToTable("Users");
    }
}

  

接下来,你就可以run一下你的网站,来体验一把ASP.NET Identity了,别忘了先把web.config里面的连接字符串改一下,方便我们自己去查看数据库,只要设置一下数据库就可以了,创建工作就交给EF吧。

  我们可以在AccountController中找到所有的相关代码。

初始化UserManager对象

1
2
3
4
5
6
7
8
9
public  AccountController()
     this ( new  UserManager<ApplicationUser>( new  UserStore<ApplicationUser>( new  ApplicationDbContext())))
{
}
public  AccountController(UserManager<ApplicationUser> userManager)
{
     UserManager = userManager;
}
public  UserManager<ApplicationUser> UserManager {  get private  set ; }

登录核心代码

1
2
3
4
5
6
var  user = await UserManager.FindAsync(model.UserName, model.Password);
if  (user !=  null )
{
     await SignInAsync(user, model.RememberMe);
     return  RedirectToLocal(returnUrl);
}

注册核心代码

1
2
var  user =  new  ApplicationUser() { UserName = model.UserName };
var  result = await UserManager.CreateAsync(user, model.Password);

 框架设计

  我们上面是直接利用VS帮助我们创建好了一些初始代码,我们也可以创建一个空白的站点,然后再把ASP.NET Identity引用进来。所需要的类库可以直接从Nuget上下载就可以了。

  主要包括ASP.NET Identity 的EF 部分的实现,有了EF的帮助我们就可以完全自定义数据结构,当然我们也只需要定义一个实体类就可以了。  

  名字就已经告诉大家了,这是ASP.NET Identity的核心了,所以主要的功能在这里面。上面那个包是ASP.NET Identity EF的实现,那么我们可以在这个核心包的基础上扩展出基于No SQL, Azure Storage 的 ASP.NET Identity实现。

  ASP.NET Identity对OWIN 认证的支持。

  最上面两个就是我们自己创建的代码,分别继承自IdentityUser和IdentityDbContext。但是与用户相关的操作实际上是通过UserManager类来完成的。。

框架实现剖析

上面代码显示和用户相关的操作是调用UserManager的方法来完成的。 我们可以在AccountController中找到UserManager的初始代码:

public AccountController(): this(new UserManager<AppUser>(new UserStore<AppUser>(new AppDbContext())))

调用UserManager,最后实现的还是UserStore,UserManager的定义:

public UserManager(IUserStore<TUser> store)
{
    this.Store = store;
}

  

 我们现在使用的是ASP.NET Identity EF的实现,所以在UserStore中,直接调用传进来的DbContext的Save操作就可以了。

扩展ASP.NET Identity - 将用户信息写入文件 

  为了熟悉AspNet.Identity的结构,我们来扩展实现一个将用户信息写入文件的组件,然后实现登录注册功能,我们就给它命名AspNet.Identity.File吧。

  1. 创建一个自己的用户类(UserIdentity)实现Microsoft.AspNet.Identity.IUser接口
  2. 创建一个自己的UserStore类实现Microsoft.AspNet.Identity.IUserStore<TUser>接口
  3. 作为演示,我们的用户类就尽量简单,只有id,用户名,和密码三个属性
  4. 我们的UserStore,也只重写了Get和Create几个基本的方法,没有重写Update。

UserIdentity.cs 代码

public class IdentityUser : IUser
{
    public string Id { get; set; }
    public string UserName { get; set;}
    public string PasswordHash{ get; set; }
    public override string ToString()
    {
        return string.Format("{0},{1},{2}", this.Id, this.UserName, this.PasswordHash);
    }
 
    public static IdentityUser FromString(string strUser)
    {
        if (string.IsNullOrWhiteSpace(strUser))
        {
            throw new ArgumentNullException("user");
        }
        var arr = strUser.Split(',');
        if (arr.Length != 3)
        {
            throw new InvalidOperationException("user is not valid");
        }
        var user = new IdentityUser();
        user.Id = arr[0];
        user.UserName = arr[1];
        user.PasswordHash = arr[2];
        return user;
    }
}

  

UserStore.cs的核心代码

// 创建用户
public async Task CreateAsync(IdentityUser user)
{
    user.Id = Guid.NewGuid().ToString();
    using (var stream = new IO.StreamWriter(_filePath, true, Encoding.UTF8))
    {
        await stream.WriteLineAsync(user.ToString());
    }
}
 
// 根据用户名找用户
public async Task<IdentityUser> FindByNameAsync(string userName)
{
    using (var stream = new IO.StreamReader(_filePath))
    {
        string line;
        IdentityUser result = null;
        while ((line = await stream.ReadLineAsync()) != null)
        {
            var user = IdentityUser.FromString(line);
            if (user.UserName == userName)
            {
                result = user;
                break;
            }
        }
        return result;
    }
}

  

AccountController.cs核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 初始化 UserManager
public  AccountController()
     this ( new  UserManager<IdentityUser>( new  UserStore(System.Web.HttpContext.Current.Server.MapPath( "~/App_Data/user.txt" ))))
{ }
// 检查用用户名密码是否正确
var  user = await UserManager.FindAsync(model.UserName, model.Password);
if  (user !=  null )
{
     // Forms 登录代码
}
// 注册用户
var  user =  new  IdentityUser() { UserName = model.UserName };
var  result = await UserManager.CreateAsync(user, model.Password);
if  (result.Succeeded)
{
     // 创建用户成功
}

   保存到txt中的用户信息

 小结

  Membership系列这三篇,从入门到精通到这里就算是结束了,不知道能不能算是园满。因为这三篇的关注度都不是很高,可能没有从多少人在乎这个玩意。不过还是要感谢@好玩一人的催促,让我坚持把这三篇写完了。可能Membership不是.NET里面非常成功的一部份,但是这并不能说它不好,而是因为像这种需求的东西如果要做成类库本身就是一项比较困难的事情,因为几乎很少有一模一样的需求。

  但是我们更应该关注的是微软是如何面对复杂多变的需求来设计框架的,如何从一大堆的零散需求中找出最核心的部份, 他们如何解耦,如何提高可扩展性和维护性的。从Membersihp引入.NET的时候给我们带来了Provider,于是我们会发现.NET2.0开始就出现了各种Provider,web.config里面各种配置。而最新的ASP.NET Identity已经不再用那样的Provider模式了,但是思想却大致相同,只不过换成了用范型来实现,用构造函数注入,这也是从MVC以来微软框架的一些特色。而我们,在追求微软技术的同时,更应该理解其内在的一些思想和本质,这样才不致于被淹没在无尽的新技术中,因为很多其实只是换汤不换药,或者我们可以用积极的话来说,微软在不断的提高开发人员的效率,并且让你写代码的时候有更好的心情。 请相信我,理解了本质,再去学习新技术,能让你效率翻倍。

  最后,还是谢谢大家一直的关注和陪伴。 

  下面的demo的链接下载,包括一个ProfileProvider的例子,和后面将用户信息写入txt文件的例子。

      AspNet.Identity.File:  http://pan.baidu.com/s/1dD5SZ1v

      ProfileProvider Demo:  http://pan.baidu.com/s/1bnnakZt

猜你喜欢

转载自www.cnblogs.com/wfy680/p/12349712.html
今日推荐