Статьи

Простая реализация Microsoft.AspNet.Identity

Вступление:

Microsoft.AspNet.Identity (известный как ASP.NET Identity) — это новая библиотека для системы членства asp.net, которая позволяет создавать современные веб-приложения ASP.NET. Прелесть ASP.NET Identity в том, что он позволяет использовать любую систему хранения. Существует реализация Microsoft.AspNet.Identity в EF, предоставленная Microsoft. Вы также можете найти некоторые реализации Microsoft.AspNet.Identity от сообщества. Например,  AspNet.Identity.RavenDB  и NHibernate.AspNet.Identity . В настоящее время реализация EF включает в себя роли и требования. Но иногда вам не нужны претензии и роли. В этой статье я покажу вам, как реализовать реализацию Microsoft.AspNet.Identity без использования утверждений и ролей.

Описание:

Прежде всего создайте приложение MVC 5. Затем внедрите IUser,

public class ApplicationUser : IUser
    {
        public ApplicationUser()
        {
            this.Id = Guid.NewGuid().ToString();
        }
        public ApplicationUser(string userName): this()
        {
            UserName = userName;
        }
        public virtual string Id { get; set; }
        public virtual string PasswordHash { get; set; }
        public virtual string SecurityStamp { get; set; }
        public virtual string UserName { get; set; }
    }

Далее нам нужен DbContet для хранения пользователей,

public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
        }
        public virtual IDbSet<ApplicationUser> Users { get; set; }
    }

а затем нам нужно реализовать IUserStore, IUserPasswordStore и IUserSecurityStampStore, 

public class MyUserStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>
    {
        UserStore<IdentityUser> userStore = new UserStore<IdentityUser>(new ApplicationDbContext());
        public MyUserStore()
        {
        }
        public Task CreateAsync(ApplicationUser user)
        {
            var context = userStore.Context as ApplicationDbContext;
            context.Users.Add(user);
            context.Configuration.ValidateOnSaveEnabled = false;
            return context.SaveChangesAsync();
        }
        public Task DeleteAsync(ApplicationUser user)
        {
            var context = userStore.Context as ApplicationDbContext;
            context.Users.Remove(user);
            context.Configuration.ValidateOnSaveEnabled = false;
            return context.SaveChangesAsync();
        }
        public Task<ApplicationUser> FindByIdAsync(string userId)
        {
            var context = userStore.Context as ApplicationDbContext;
            return context.Users.Where(u => u.Id.ToLower() == userId.ToLower()).FirstOrDefaultAsync();
        }
        public Task<ApplicationUser> FindByNameAsync(string userName)
        {
            var context = userStore.Context as ApplicationDbContext;
            return context.Users.Where(u => u.UserName.ToLower() == userName.ToLower()).FirstOrDefaultAsync();
        }
        public Task UpdateAsync(ApplicationUser user)
        {
            var context = userStore.Context as ApplicationDbContext;
            context.Users.Attach(user);
            context.Entry(user).State = EntityState.Modified;
            context.Configuration.ValidateOnSaveEnabled = false;
            return context.SaveChangesAsync();
        }
        public void Dispose()
        {
            userStore.Dispose();
        }

        public Task<string> GetPasswordHashAsync(ApplicationUser user)
        {
            var identityUser = ToIdentityUser(user);
            var task = userStore.GetPasswordHashAsync(identityUser);
            SetApplicationUser(user, identityUser);
            return task;
        }
        public Task<bool> HasPasswordAsync(ApplicationUser user)
        {
            var identityUser = ToIdentityUser(user);
            var task = userStore.HasPasswordAsync(identityUser);
            SetApplicationUser(user, identityUser);
            return task;
        }
        public Task SetPasswordHashAsync(ApplicationUser user, string passwordHash)
        {
            var identityUser = ToIdentityUser(user);
            var task = userStore.SetPasswordHashAsync(identityUser, passwordHash);
            SetApplicationUser(user, identityUser);
            return task;
        }
        public Task<string> GetSecurityStampAsync(ApplicationUser user)
        {
            var identityUser = ToIdentityUser(user);
            var task = userStore.GetSecurityStampAsync(identityUser);
            SetApplicationUser(user, identityUser);
            return task;
        }
        public Task SetSecurityStampAsync(ApplicationUser user, string stamp)
        {
            var identityUser = ToIdentityUser(user);
            var task = userStore.SetSecurityStampAsync(identityUser, stamp);
            SetApplicationUser(user, identityUser);
            return task;
        }
        private static void SetApplicationUser(ApplicationUser user, IdentityUser identityUser)
        {
            user.PasswordHash = identityUser.PasswordHash;
            user.SecurityStamp = identityUser.SecurityStamp;
            user.Id = identityUser.Id;
            user.UserName = identityUser.UserName;
        }
        private IdentityUser ToIdentityUser(ApplicationUser user)
        {
            return new IdentityUser
            {
                Id = user.Id,
                PasswordHash = user.PasswordHash,
                SecurityStamp = user.SecurityStamp,
                UserName = user.UserName
            };
        }
    }

Для хэша пароля и отметки безопасности я использую реализацию UserStore для упрощения работы. Наконец, нам просто нужно изменить конструктор AccountController, чтобы использовать нашу реализацию MyUserStore,

public AccountController()
            : this(new UserManager<ApplicationUser>(new MyUserStore()))
        {
        }

        public AccountController(UserManager<ApplicationUser> userManager)
        {
            UserManager = userManager;
        }

Резюме:

Новый Microsoft.AspNet.Identity позволяет очень легко расширить систему хранения. В этой статье я показал вам, как реализовать простую реализацию Microsoft.AspNet.Identity. Надеюсь, вам понравилась моя статья.