Начало работы с ASP.NET Identity

в 7:55, , рубрики: .net, asp.net mvc, OWIN, метки: ,

Многие из вас должны знать, что выход ASP.NET MVC 5 ознаменовался переходом на новую систему авторизации под названием ASP.NET Identity. Разработчики фреймворка настоятельно рекомендуют переходить на новую систему, называя основными ее преимуществами возможность внедрения в абсолютно любой проект (ASP.NET MVC, Web Forms, Web Pages, Web API и SignalR), простую социальную интеграцию, работу на OWIN, установку и обновление посредством NuGet и другие. Присмотревшись внимательнее к ASP.NET Identity, можно без зазрения совести сказать, что это — следующий этап в развитии веб-программирования на ASP.NET. В данном посте я размещу простой туториал для начала работы с ASP.NET Identity.

Побродив немножко по интернету в поисках доступного туториала по реализации системы авторизации в проекте MVC 5, я нашел определенное количество тематических статей, но практически все они были ориентированы на использование Entity Framework как хранилища пользовательских данных. Даже корневой ресурс, к моему великому расстройству, не смог в должной степени раскрыть тему и ответить на все интересующие вопросы.

Пусть у нас имеется MVC-проект, где мы бы хотели использовать самые последние технологии, в частности Owin, Katana и конечно же ASP.NET Identity. Если вдруг термин Owin вводит вас в замешательство, рекомендую прочесть статью.

1. Основные библиотеки, которые нам потребуются: Microsoft.AspNet.Identity.Core, Microsoft.Owin, Microsoft.Owin.Security + все, от них зависимые и зависящие. Легко устанавливаются при помощи NuGet Package Manager. Через консоль NuGet это можно сделать так:

Install-Package Microsoft.AspNet.Identity.Core

2. Реализуем основные классы:

public class ApplicationUser : IUser
{
        public ApplicationUser(string name)
        {            
            Id = Guid.NewGuid().ToString();
            UserName = name;
        }

        public string Id { get; private set; }
        public string UserName { get; set; }
}

Интерфейс Microsoft.AspNet.Identity.IUser требует реализации полей Id и UserName. Помимо этого вы можете добавить нужные вам поля (Email, Password, City и т.д.)

public class CustomUserStore : IUserStore<ApplicationUser>
{
        static readonly List<ApplicationUser> Users = new List<ApplicationUser>();

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public Task CreateAsync(ApplicationUser user)
        {
            return Task.Factory.StartNew(() => Users.Add(user));
        }

        public Task UpdateAsync(ApplicationUser user)
        {
            throw new NotImplementedException();
        }

        public Task DeleteAsync(ApplicationUser user)
        {
            throw new NotImplementedException();
        }

        public Task<ApplicationUser> FindByIdAsync(string userId)
        {
            throw new NotImplementedException();
        }

        public Task<ApplicationUser> FindByNameAsync(string userName)
        {
            return Task<ApplicationUser>.Factory.StartNew(() => Users.FirstOrDefault(u => u.UserName == userName));
        }
}

CustomUserStore, как понятно из названия, является хранилищем пользователей и включает базовые методы (Create, Update, Delete) для работы с ними. Здесь я использую для хранения статическое поле Users. Здесь же можно прикрутить любое, подходящее для вас хранилище. Также нельзя не обратить внимание на тип возвращаемого значения — Task и Task. Это означает, что методы будут выполняться асинхронно. По этой теме есть неплохие материалы на хабре (например, вот).

public class CustomUserManager : UserManager<ApplicationUser>
{
        public CustomUserManager(CustomUserStore store)
            : base(store)
        {
                this.PasswordHasher = new CustomPasswordHasher();
        }

        public override Task<ApplicationUser> FindAsync(string userName, string password)
        {
            Task<ApplicationUser> taskInvoke = Task<ApplicationUser>.Factory.StartNew(() =>
            {               
                PasswordVerificationResult result = this.PasswordHasher.VerifyHashedPassword(userName, password);
                if (result == PasswordVerificationResult.SuccessRehashNeeded)
                {    
                    return Store.FindByNameAsync(userName).Result;
                }
                return null;
            });
            return taskInvoke;
        }
}

public class CustomPasswordHasher : PasswordHasher
{
        public override string HashPassword(string password)
        {
            return base.HashPassword(password);
        }

        public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
        {           
            if (true)
            {
                return PasswordVerificationResult.SuccessRehashNeeded;
            }
            else
            {
                return PasswordVerificationResult.Failed;
            }
        }
}

CustomUserManager — главный класс, методы которого мы будем вызывать для манипулирования пользовательскими данными(замена старому Membership Provider). Он должен являться наследником Microsoft.AspNet.Identity.UserManager, который содержит множество виртуальных методов. В данном случае мы переопределили метод FindAsync(), в котором для примера сначала проверяется пароль, и в случае успеха возвращается юзер. Как вы видите, в конструкторе UserManeger мы определили собственный PasswordHasher — класс, предназначенный для управления паролями. Тело метода VerifyHashedPassword имеет демонстрационный вид. Вы же можете там написать свою логику проверки пароля.

3. Настраиваем приложение на работу с нашим CustomUserManager. Для этого в файле Startup.cs, который исполняется сборкой Owin при запуске приложения, добавляем строку:

        app.CreatePerOwinContext(CustomUserManager.Create);

4. Используем CustomUserManager внутри контроллера:

public class TestController : ApiController
{
        private static CustomUserManager _customUserManager;

        public CustomUserManager UserManager
        {
            get
            {
                return _customUserManager ??
                       (_customUserManager = HttpContext.Current.GetOwinContext().GetUserManager<CustomUserManager>());
            }
        }
        public async Task<bool> Authenticate(string name, string password)
        {
           if (await UserManager.FindAsync(name, password) != null)
            {
                return true;
            }

            return false;
        }
}

Вы можете использовать те методы UserManager, которые вы переопределили, а также стандартный набор методов класса CustomUserStore (они вызываются по умолчанию, если вы используете одноименные методы вашего UserManager), которые должны быть определены в обязательном порядке.

5. Для использования стандартных атрибутов MVC [Authorize] установите нужный вам тип авторизации в классе Startup. Например:

public class Startup
{
        public void Configuration(IAppBuilder app)
        {
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                        LoginPath = new PathString("/Account/Login")
                });
        }
}

Список использованных ресурсов:
Simple Asp.net Identity Core Without Entity Framework
ASP.NET Identity 2.0 Cookie & Token Authentication

P.S. Данный материал является дебютным и, конечно же, не претендует на исчерпывающий мануал по ASP.NET Identity. Рассчитан на людей, знакомых с технологией MVC, желающих познакомиться с новой системой авторизации.

Автор: mpavlov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js