ASP.NET Identity в многоуровневой архитектуре. Уровень представления

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 11.11.2015

Вернемся к самому первому проекту, который был создан, - к проекту UserStore.WEB и вначаеле добавим в него следующие пакеты Nuget:

Microsoft.AspNet.Identity.Core
Microsoft.AspNet.Identity.Owin
Microsoft.Owin.Host.SystemWeb
Owin

И также добавим в проект ссылку на проект BLL.

Данные пакеты позволят нам использовать аутентификацию AspNet Identity вместе с OWIN. И вначале в папку App_Start добавим класс Startup:

using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using UserStore.BLL.Services;
using Microsoft.AspNet.Identity;
using UserStore.BLL.Interfaces;

[assembly: OwinStartup(typeof(UserStore.App_Start.Startup))]

namespace UserStore.App_Start
{
    public class Startup
    {
        IServiceCreator serviceCreator = new ServiceCreator();
        public void Configuration(IAppBuilder app)
        {
            app.CreatePerOwinContext<IUserService>(CreateUserService);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
            });
        }

        private IUserService CreateUserService()
        {
            return serviceCreator.CreateUserService("DefaultConnection");
        }
    }
}

С помощью фабрики сервисов здесь создается сервис для работы с сервисами:

IServiceCreator serviceCreator = new ServiceCreator();

Потом сервис региструется контекстом OWIN:

app.CreatePerOwinContext<IUserService>(CreateUserService);

При этом здесь предполагается, что в файле web.config имеется строка подключения DefaultConnection, которая передается в метод serviceCreator.CreateUserService("DefaultConnection").

Если бы создали бы проект с аутентификацией, то примерно также работала регистрация контекстом OWIN менеджера пользователей.

Но опять же нам необязательно использовать абстрактную фабрику для создания сервиса, мы также могли бы воспользоваться контейнерами внедрения зависимостей для установки всех зависимостей.

Далее добавим в папку Controllers новый контроллер AccountController:

using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using Microsoft.AspNet.Identity.Owin;
using System.Threading.Tasks;
using UserStore.Models;
using UserStore.BLL.DTO;
using System.Security.Claims;
using UserStore.BLL.Interfaces;
using UserStore.BLL.Infrastructure;

namespace UserStore.Controllers
{
    public class AccountController : Controller
    {
        private IUserService UserService
        {
            get
            {
                return HttpContext.GetOwinContext().GetUserManager<IUserService>();
            }
        }

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginModel model)
        {
            await SetInitialDataAsync();
            if (ModelState.IsValid)
            {
                UserDTO userDto = new UserDTO { Email = model.Email, Password = model.Password};
                ClaimsIdentity claim = await UserService.Authenticate(userDto);
                if (claim == null)
                {
                    ModelState.AddModelError("", "Неверный логин или пароль.");
                }
                else
                {
                    AuthenticationManager.SignOut();
                    AuthenticationManager.SignIn(new AuthenticationProperties
                    {
                        IsPersistent = true
                    }, claim);
                    return RedirectToAction("Index", "Home");
                }
            }
            return View(model);
        }

        public ActionResult Logout()
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Index", "Home");
        }

        public ActionResult Register()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterModel model)
        {
			await SetInitialDataAsync();
            if (ModelState.IsValid)
            {
                UserDTO userDto = new UserDTO
                {
                    Email = model.Email,
                    Password = model.Password,
                    Address = model.Address,
                    Name = model.Name,
                    Role = "user"
                };
                OperationDetails operationDetails = await UserService.Create(userDto);
                if (operationDetails.Succedeed)
                    return View("SuccessRegister");
                else
                    ModelState.AddModelError(operationDetails.Property, operationDetails.Message);
            }
            return View(model);
        }
		private async Task SetInitialDataAsync()
        {
			await UserService.SetInitialData(new UserDTO
            {
                Email = "somemail@mail.ru",
                UserName = "somemail@mail.ru",
                Password = "ad46D_ewr3",
                Name = "Семен Семенович Горбунков",
                Address = "ул. Спортивная, д.30, кв.75",
                Role="admin",
            }, new List<string> { "user", "admin" });
		}
    }
}

Поскольку ранее мы зарегитрировали сервис пользователей через контекст OWIN, то теперь мы можем получить этот сервис с помощью метода

HttpContext.GetOwinContext().GetUserManager<IUserService>()

В методе Login производится вход пользователя на сайт. Для этого используется модель LoginModel:

public class LoginModel
{
    [Required]
    public string Email { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

Причем, чтобы гарантировать, что в базе данных будут начальные данные, в методе Login также запускается метод SetInitialDataAsync().

Далее с помощью метода UserService.Authenticate() получаем объект ClaimsIdentity, который затем используется для создания аутентификационного тикета, сохраняемого в куках.

В методе Register для регистрации используется модель RegisterModel:

public class RegisterModel
{
    [Required]
    public string Email { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Compare("Password")]
    public string ConfirmPassword { get; set; }
    [Required]
    public string Address { get; set; }
    [Required]
    public string Name { get; set; }
}

В самом методе Register с помощью вызова UserService.Create() в базу данных будет добавляться новый пользователь.

Ну и естественнно для методов Login и Register должны быть определены представления, которые используют соответственно модели LoginModel и RegisterModel.

И после определения системы аутентификации мы можем использовать атрибут Authorize и роли для разграничения доступа.

В итоге проект будет выглядеть следующим образом:

ASP.NET Identity in Presentation Layer

Ссылка на итоговый проект

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850