Учебники

ASP.NET Core — Конфигурация идентичности

В этой главе мы установим и настроим инфраструктуру Identity, что займет немного времени. Если вы зайдете в Visual Studio и создадите новое приложение ASP.NET Core и выберете полный шаблон веб-приложения с аутентификацией, настроенной для отдельных учетных записей пользователей, этот новый проект будет включать все биты инфраструктуры Identity, настроенной для вас.

Конфигурация личности

Мы начали с пустого проекта. Теперь мы настроим платформу Identity с нуля, что является хорошим способом узнать обо всех компонентах полного шаблона приложения, потому что это может сбить с толку, если вы не проработали подробно все коды.

Для начала нам нужно установить зависимость Microsoft.AspNet.Identity . Мы продолжим, установив Microsoft.AspNet.Identity.EntityFramework и затем внедрив платформу Identity, которая работает с Entity Framework.

  • Если мы возьмем зависимость от Identity.EntityFramework, пакет будет включать пакет Identity.

  • Если вы создаете свои собственные хранилища данных, вы можете работать только с пакетом Identity.

  • После того, как наши зависимости установлены, мы можем создать пользовательский класс User со всей информацией, которую мы хотим сохранить о пользователе.

  • Для этого приложения мы собираемся наследовать от класса, предоставляемого платформой Identity, и этот класс предоставит нам все необходимое, например, свойство Username и место для хранения хешированных паролей.

Если мы возьмем зависимость от Identity.EntityFramework, пакет будет включать пакет Identity.

Если вы создаете свои собственные хранилища данных, вы можете работать только с пакетом Identity.

После того, как наши зависимости установлены, мы можем создать пользовательский класс User со всей информацией, которую мы хотим сохранить о пользователе.

Для этого приложения мы собираемся наследовать от класса, предоставляемого платформой Identity, и этот класс предоставит нам все необходимое, например, свойство Username и место для хранения хешированных паролей.

ASP.NET Identity

  • Нам также потребуется изменить наш класс FirstAppDemoDbContext, чтобы он наследовал от класса IdentityDb инфраструктуры Identity .

  • IdentityDb дает нам все, что нам нужно хранить как пользовательскую информацию в Entity Framework. После того, как у нас есть класс User и DBContext , нам нужно будет настроить службы Identity в приложении с помощью метода ConfigureServices класса Startup.

  • Точно так же, как когда нам нужно было добавить сервисы для поддержки инфраструктуры MVC, каркасу Identity нужны сервисы, добавленные в приложение для работы.

  • Эти службы включают в себя такие службы, как служба UserStore и SignInManager .

  • Мы будем внедрять эти сервисы в наш контроллер для создания пользователей и выдачи файлов cookie в соответствующее время.

  • Наконец, во время запуска метода Configure нам потребуется добавить промежуточное программное обеспечение Identity.

  • Это промежуточное программное обеспечение не только поможет превратить файлы cookie в личность пользователя, но также гарантирует, что пользователь не увидит пустую страницу с ответом 401.

Нам также потребуется изменить наш класс FirstAppDemoDbContext, чтобы он наследовал от класса IdentityDb инфраструктуры Identity .

IdentityDb дает нам все, что нам нужно хранить как пользовательскую информацию в Entity Framework. После того, как у нас есть класс User и DBContext , нам нужно будет настроить службы Identity в приложении с помощью метода ConfigureServices класса Startup.

Точно так же, как когда нам нужно было добавить сервисы для поддержки инфраструктуры MVC, каркасу Identity нужны сервисы, добавленные в приложение для работы.

Эти службы включают в себя такие службы, как служба UserStore и SignInManager .

Мы будем внедрять эти сервисы в наш контроллер для создания пользователей и выдачи файлов cookie в соответствующее время.

Наконец, во время запуска метода Configure нам потребуется добавить промежуточное программное обеспечение Identity.

Это промежуточное программное обеспечение не только поможет превратить файлы cookie в личность пользователя, но также гарантирует, что пользователь не увидит пустую страницу с ответом 401.

Давайте теперь следуем инструкциям ниже.

Шаг 1 — Нам нужно продолжить, добавив зависимость от платформы Identity. Давайте добавим зависимость Microsoft.AspNet.Identity.EntityFramework в файл project.json. Это будет включать в себя все другие необходимые пакеты удостоверений, которые нам нужны.

{ 
   "version": "1.0.0-*", 
   "compilationOptions": { 
      "emitEntryPoint": true 
   },  
  
   "dependencies": { 
      "Microsoft.AspNet.Mvc":  "6.0.0-rc1-final", 
      "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", 
      "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", 
      "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", 
      "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", 
      "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", 
      "EntityFramework.Commands": "7.0.0-rc1-final", 
      "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final", 
      "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final" 
   },  
   
   "commands": { 
      "web": "Microsoft.AspNet.Server.Kestrel", 
      "ef": "EntityFramework.Commands" 
   },  
  
   "frameworks": { 
      "dnx451": { }, 
      "dnxcore50": { } 
   },  
   
   "exclude": [ 
      "wwwroot", 
      "node_modules" 
   ], 
    
   "publishExclude": [ 
      "**.user", 
      "**.vspscc" 
   ] 
} 

Шаг 2 — Сохраните этот файл. Visual Studio восстанавливает пакеты, и теперь мы можем добавить наш класс User. Давайте добавим класс User, щелкнув правой кнопкой мыши на папке Models и выбрав Add → Class.

Параметры кода и класса

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

Шаг 3 — Давайте выведем класс User из класса, предоставленного платформой Identity. Это класс IdentityUser, который находится в пространстве имен Identity.EntityFramework.

using Microsoft.AspNet.Identity.EntityFramework; 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks;  

namespace FirstAppDemo.Models { 
   public class User : IdentityUser { 
   } 
}

Шаг 4 — Теперь давайте перейдем к IdentityUser, поместим курсор на этот символ и нажмите F12, чтобы увидеть представление метаданных Visual Studio.

#region Assembly Microsoft.AspNet.Identity.EntityFramework, Version = 3.0.0.0,   

namespace Microsoft.AspNet.Identity.EntityFramework { 
   public class IdentityUser : IdentityUser<string> { 
      public IdentityUser(); 
      public IdentityUser(string userName); 
   } 
}

Шаг 5. Вы можете видеть, что IdentityUser является производным от IdentityUser строки. Вы можете изменить тип первичного ключа, унаследовав его от IdentityUser и указав наш параметр универсального типа. Вы также можете хранить вещи с первичным ключом, который в идеале является целочисленным значением.

Шаг 6 — Давайте теперь поместим курсор на IdentityUser строки и снова нажмите F12, чтобы перейти к представлению метаданных.

Личность пользователя

Теперь вы можете видеть всю информацию, связанную с пользователем по умолчанию. Информация включает в себя следующее —

  • Поля, которые мы не будем использовать в этом приложении, но доступны для использования.

  • Платформа Identity может отслеживать количество неудачных попыток входа в систему для конкретного пользователя и может блокировать эту учетную запись в течение определенного периода времени.

  • Поля для хранения PasswordHash, PhoneNumber. Мы будем использовать два важных поля — PasswordHash и UserName.

  • Мы также будем неявно использовать первичный ключ и свойство ID пользователя. Вы также можете использовать это свойство, если вам нужно выполнить запрос для конкретного пользователя.

Поля, которые мы не будем использовать в этом приложении, но доступны для использования.

Платформа Identity может отслеживать количество неудачных попыток входа в систему для конкретного пользователя и может блокировать эту учетную запись в течение определенного периода времени.

Поля для хранения PasswordHash, PhoneNumber. Мы будем использовать два важных поля — PasswordHash и UserName.

Мы также будем неявно использовать первичный ключ и свойство ID пользователя. Вы также можете использовать это свойство, если вам нужно выполнить запрос для конкретного пользователя.

Шаг 7 — Теперь нам нужно убедиться, что пользователь включен в наш DBContext. Итак, давайте откроем FirstAppDemoDBContext, который есть в нашем приложении, и вместо того, чтобы выводить его напрямую из DBContext, который является встроенным базовым классом Entity Framework, нам теперь нужно извлечь его из IdentityDbContext.

using Microsoft.AspNet.Identity.EntityFramework; 
using Microsoft.Data.Entity;  

namespace FirstAppDemo.Models { 
   public class FirstAppDemoDbContext : IdentityDbContext<User> { 
      public DbSet<Employee> Employees { get; set; }  
      
      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { 
         optionsBuilder.UseSqlServer("Data Source = (localdb)\\MSSQLLocalDB;
            Initial Catalog = FirstAppDemo;Integrated Security = True;
            Connect Timeout = 30;Encrypt = False;TrustServerCertificate = True;
            ApplicationIntent = ReadWrite;MultiSubnetFailover = False"); 
      } 
   } 
}        

Шаг 8 — Класс IdentityDbContext также находится в пространстве имен Microsoft.AspNet.Identity.EntityFramework, и мы можем указать тип пользователя, который он должен хранить. Таким образом, любые дополнительные поля, которые мы добавляем в класс User, попадают в базу данных.

  • IdentityDbContext предоставляет дополнительные наборы данных DbSets не только для хранения пользователя, но и для информации о пользовательских ролях и заявках пользователей.

  • Наш пользовательский класс готов сейчас. Наш класс FirstAppDemoDbContext настроен для работы со структурой Identity.

  • Теперь мы можем перейти к Configure и ConfigureServices, чтобы настроить Identity Framework.

IdentityDbContext предоставляет дополнительные наборы данных DbSets не только для хранения пользователя, но и для информации о пользовательских ролях и заявках пользователей.

Наш пользовательский класс готов сейчас. Наш класс FirstAppDemoDbContext настроен для работы со структурой Identity.

Теперь мы можем перейти к Configure и ConfigureServices, чтобы настроить Identity Framework.

Шаг 9 — Давайте начнем с ConfigureServices . В дополнение к нашим службам MVC и службам Entity Framework нам необходимо добавить наши службы идентификации. Это добавит все сервисы, на которые опирается платформа Identity для выполнения своей работы.

public void ConfigureServices(IServiceCollection services) { 
   services.AddMvc(); 
   
   services.AddEntityFramework() 
      .AddSqlServer() 
      .AddDbContext<FirstAppDemoDbContext>
      (option => option.UseSqlServer(Configuration["database:connection"]));  
      
   services.AddIdentity<User, IdentityRole>() 
      .AddEntityFrameworkStores<FirstAppDemoDbContext>(); 
}
  • Метод AddIdentity принимает два параметра общего типа — тип объекта пользователя и тип объекта роли.

  • Два параметра универсального типа — это типы нашего пользователя — класс User, который мы только что создали, и класс Role, с которым мы хотим работать. Теперь мы будем использовать встроенную IdentityRole. Этот класс находится в пространстве имен EntityFramework.

  • Когда мы используем Entity Framework с Identity, нам также необходимо вызвать второй метод — AddEntityFrameworkStores.

  • Метод AddEntityFrameworkStores настроит такие службы, как UserStore, служба, используемая для создания пользователей и проверки их паролей.

Метод AddIdentity принимает два параметра общего типа — тип объекта пользователя и тип объекта роли.

Два параметра универсального типа — это типы нашего пользователя — класс User, который мы только что создали, и класс Role, с которым мы хотим работать. Теперь мы будем использовать встроенную IdentityRole. Этот класс находится в пространстве имен EntityFramework.

Когда мы используем Entity Framework с Identity, нам также необходимо вызвать второй метод — AddEntityFrameworkStores.

Метод AddEntityFrameworkStores настроит такие службы, как UserStore, служба, используемая для создания пользователей и проверки их паролей.

Шаг 10. Следующие две строки — все, что нам нужно для настройки служб для приложения.

services.AddIdentity<User, IdentityRole>() 
   .AddEntityFrameworkStores<FirstAppDemoDbContext>();

Шаг 11 — Нам также нужно добавить промежуточное программное обеспечение. Расположение того, куда мы вставляем промежуточное ПО, важно, потому что, если мы вставим промежуточное ПО слишком поздно в конвейер, у него никогда не будет возможности обработать запрос.

И если нам требуются проверки авторизации внутри наших контроллеров MVC, нам нужно вставить промежуточное ПО Identity перед платформой MVC, чтобы убедиться, что файлы cookie, а также ошибки 401 успешно обрабатываются.

public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler();  
   
   app.UseDeveloperExceptionPage(); 
   app.UseRuntimeInfoPage();  
  
   app.UseFileServer();  
   
   app.UseIdentity(); 
   app.UseMvc(ConfigureRoute);  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
} 

Шаг 12. В то место, куда мы вставляем промежуточное ПО, мы добавляем промежуточное ПО Identity. Ниже приведена полная реализация файла Startup.cs.

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http;

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration; 

using FirstAppDemo.Services; 
using Microsoft.AspNet.Routing; 
using System; 

using FirstAppDemo.Entities; 
using Microsoft.Data.Entity; 

using FirstAppDemo.Models; 
using Microsoft.AspNet.Identity.EntityFramework;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() 
            .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }  
        
      // This method gets called by the runtime.
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID = 398940 
      public void ConfigureServices(IServiceCollection services) { 
         services.AddMvc(); 
            services.AddEntityFramework() 
            .AddSqlServer() 
            .AddDbContext<FirstAppDemoDbContext>(option => 
            option.UseSqlServer(Configuration["database:connection"]));  
         
         services.AddIdentity<User, IdentityRole>() 
            .AddEntityFrameworkStores<FirstAppDemoDbContext>(); 
      }
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         app.UseDeveloperExceptionPage(); 
         app.UseRuntimeInfoPage();  
         app.UseFileServer();  
         app.UseIdentity(); 
         app.UseMvc(ConfigureRoute);  
         
         app.Run(async (context) => { 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         }); 
      }  
      private void ConfigureRoute(IRouteBuilder routeBuilder) { 
         //Home/Index 
         routeBuilder.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}"); 
      }  
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
   } 
}

Шаг 13 — Давайте теперь двигаться вперед, создав приложение. В следующей главе нам нужно добавить еще одну миграцию Entity Framework, чтобы убедиться, что у нас есть схема Identity в нашей базе данных SQL Server.