Регистрация пользователя MVC и вход в систему с помощью ASP.NET Core Identity

  • Михаил
  • 12 мин. на прочтение
  • 173
  • 09 Dec 2022
  • 09 Dec 2022

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

Обсуждаемые подтемы:

  • Как добавить идентификацию ASP.NET Core в приложение MVC.
  • Настройте удостоверение ASP.NET Core.
  • Настройка дизайна Identity.UI.
  • Следующий шаг.

Вступление

ASP.NET Core Identity — это API, который предоставляет как пользовательский интерфейс (UI), так и функции для аутентификации, регистрации, авторизации и т. д. Модули/API, подобные этому, действительно будут полезны и ускорят процесс разработки. Он поставляется с ASP.NET Core Framework и ранее использовался во многих приложениях. Что делает API более надежным и заслуживающим доверия.

ASP.NET Core MVC с аутентификацией пользователя можно легко выполнить с помощью  Identity.UI . При создании проекта MVC вам просто нужно выбрать аутентификацию в качестве отдельных учетных записей пользователей.

Остальное будет обрабатываться пользовательским интерфейсом ASP.NET Core Identity. Он уже содержит страницы бритвенного просмотра и внутренние коды для системы аутентификации. Но это не то, что мы хотим в большинстве случаев. мы хотим  настроить ASP.NET Core Identity  в соответствии с нашими требованиями. Это то, что мы делаем здесь.

Создание проекта ASP.NET Core MVC

Прежде всего, я создам совершенно новое приложение ASP.NET Core MVC без какой-либо аутентификации. Мы могли бы добавить ASP.NET Core Identity позже в проект.

В Visual Studio 2019 выберите  «Файл» > «Создать» > «Проект» (Ctrl + Shift + N) . В новом окне проекта выберите ASP.NET Core Web Application.

После того, как вы укажете название проекта и местоположение. Откроется новое окно следующего содержания: выберите  «Веб-приложение (модель-представление-контроллер)»,  снимите  флажок «Конфигурация HTTPS»  и НЕ выбирайте какой-либо метод аутентификации. Вышеупомянутые шаги создадут новый проект ASP.NET Core MVC.

Добавление удостоверения ASP.NET Core в существующий проект

Чтобы добавить ASP.NET Core Identity в существующий проект, щелкните проект правой кнопкой мыши и выберите «  Добавить» > «Новый шаблонный элемент» . В открывшемся окне выберите  «Идентификация»  на левой панели и нажмите «Добавить». Откроется другое окно, как показано ниже.


С помощью этого окна мы пытаемся переопределить выбранные операции из Identity. Здесь я выбрал «Войти и зарегистрироваться», чтобы продемонстрировать вам, насколько мы можем настроить API. По умолчанию   для страниц идентификации выбран файл _Layout.cshtml . Теперь укажите имена классов C# для контекста данных и пользовательской модели, используя кнопку + справа. Наконец, нажмите  Добавить. Затем в каталог проекта будет добавлена ​​новая  область идентификации  с выбранными страницами и соответствующими файлами.

Теперь обновите   файл Startup.cs , как показано ниже.

...

public void ConfigureServices(IServiceCollection services)
{
    ...
    //to be added
    services.AddRazorPages();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseRouting();

    //to be added
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        //to be added
        endpoints.MapRazorPages();
    });
}

ASP.NET Core Identity.UI использует страницы Razor для пользовательского интерфейса. Следовательно  ConfigureServices, в , мы должны позвонить  AddRazorPages из  servicesASP.NET Core Identity  содержит следующие маршруты,

  • /Идентификация/Учетная запись/Вход
  • /Идентификация/Учетная запись/Выход
  • /Идентификация/Учетная запись/Регистрация
  • так далее

Чтобы добавить эти маршруты в приложение,  Configure функцию Inside, при вызове  UseEndpoints функции мы должны вызвать  MapRazorPagesфункцию. UseAuthentication вызывается для добавления аутентификации пользователя в приложение. Теперь, если вы перейдете по упомянутым URL-адресам удостоверений, вы увидите соответствующую страницу интерфейса для входа и регистрации пользователя. Теперь давайте начнем каждый из них один за другим.

Настройка удостоверения ASP.NET Core

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

  • UserName
  • Email
  • PhoneNumber
  • PasswordHash - для зашифрованного пароля
  • и т.п.

Давайте добавим еще несколько свойств, таких как имя и фамилия, в класс модели. Для этого мы можем определить новый класс модели  ApplicationUser, который наследуется от класса модели API  IdentityUser.

// new file : /Areas/Identity/Data/ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
    [PersonalData]
    [Column(TypeName ="nvarchar(100)")]
    public string FirstName { get; set; }

    [PersonalData]
    [Column(TypeName = "nvarchar(100)")]
    public string LastName { get; set; }
}

Существует класс DbContext  AuthDbContext [/Areas/Identity/Data/]. Экземпляр класса будет создан путем внедрения зависимостей ASP.NET Core в IdentityHostingStartup.cs [/Areas/Identity/].

builder.ConfigureServices((context, services) => {
                services.AddDbContext<AuthDbContext>(options =>
                    options.UseSqlServer(
                        context.Configuration.GetConnectionString("AuthDbContextConnection")));
  ...
}

Строка подключения  AuthDbContextConnection сохраняется в appSettings.json. При необходимости вы можете изменить экземпляр SQL Server или базу данных, как показано ниже.

"ConnectionStrings": {
    "AuthDbContextConnection": "Server=(local)\\sqlexpress;Database=MVCAuthDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }

Теперь мы можем создать физическую БД с помощью миграции БД. В обозревателе решений выберите проект, перейдите в  Инструменты > Диспетчер пакетов NuGet > Консоль диспетчера пакетов. Затем выполните следующие команды одну за другой.

Add-Migration "InitialCreate"
Update-Database

После успешной миграции БД, наряду с другими таблицами удостоверений, в  таблице  AspNetUsers вы  могли видеть новые столбцы для имени и фамилии.

Настройка дизайна

Прежде всего, чтобы добавить визуальные эффекты в приложение, ссылки на таблицы стилей Font Awesome и Google Font Roboto добавляются в макет MVC по умолчанию —  Views/Shared/_Layout.cshml .

...
<head>
    ...
    <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" data-rocket-async="style" as="style" onload="this.onload=null;this.rel='stylesheet'" onerror="this.removeAttribute('data-rocket-async')"  />

</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Authentication System</a>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
					//partial layout for logged in user.
                    <partial name="_LoginPartial" ></partial>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>
    ..

В этом макете вы могли видеть частичный рендер для  _LoginPartialон показывает элементы HTML для зарегистрированного пользователя с кнопкой выхода. В настоящее время тот же файл показывает ссылки для входа и регистрации. нам не нужно показывать их в заголовке. поэтому обновите  _LoginPartial , как показано ниже.

@using Microsoft.AspNetCore.Identity
@using Project.Areas.Identity.Data

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
    </li>
    <li class="nav-item">
        <form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })">
            <button id="logout" type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
</ul>

Теперь давайте добавим следующие правила css в глобальную таблицу стилей [wwwroot/css/site.css] следующим образом.

...
body {
    font-family: 'Roboto', sans-serif;
}

/*for tab control*/
div.login-logout-tab div.card-header {
    padding: 0px 0px 12px 0px;
}

div.login-logout-tab ul.nav-tabs {
    margin: 0px 0px -12px 0px;
}

div.login-logout-tab li.nav-item {
    width: 50%;
}

div.login-logout-tab a.nav-link {
    font-size: 25px;
    color: #495057;
    text-align:center;
}

div.card-content{
    padding : 10px 20px;
}

/*login form*/
div.login-form-icon{
    text-align:center;
}

Теперь мы собираемся показать форму входа и регистрации рядом во вкладке. Для этого нам нужна вложенная страница макета для страницы входа и регистрации. Итак, давайте создадим  _AuthLayout.cshtml  в /Areas/Identity/Pages. Для этого щелкните правой кнопкой мыши папку «Страницы», выберите «Добавить»> «Новый элемент». Выберите  Razor Layout,  назовите файл  _AuthLayout.cshtml. Замените файл, как показано ниже.

@{
    Layout = "/Views/Shared/_Layout.cshtml";
}

<div class="row">
    <div class="col-md-6 offset-md-3">
        <div class="card login-logout-tab">
            <div class="card-header">
                <ul class="nav nav-tabs card-header-tabs">
                    <li class="nav-item">
                        <a class="nav-link" href='/Identity/Account/Login'>Sign In</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href='/Identity/Account/Register'>Sign Up</a>
                    </li>
                </ul>
            </div>
            <div class="card-content">
                <div class="col-md-12">
                    @RenderBody()
                </div>
            </div>
        </div>
    </div>
</div>

@section Scripts{
    @RenderSection("Scripts", required: false)
    <script>
        $(function () {
            var current = location.pathname;
            $('.nav-tabs li a').each(function () {
                var $this = $(this);
                if (current.indexOf($this.attr('href')) !== -1) {
                    $this.addClass('active');
                }
            })
        })
  <!-- put script end tag here !-->
}

мы хотим показать элемент управления вкладками следующим образом.

Прежде всего, у нас есть основной макет (_Layout.cshtml), а затем внутри него вложенный макет (_AuthLayout). Вместо  @RenderBody()  мы должны показывать html с соответствующих бритвенных страниц на основе URL-адресов. Это может быть страница входа или регистрации. Внутри раздела сценария, на основе текущего URL-адреса, мы добавили класс «активный» к соответствующему заголовку вкладки.

Регистрация пользователя

Теперь давайте посмотрим, что нам нужно сделать в форме регистрации пользователя, которая находится внутри /Areas/Identity/Pages/Account как  Register.cshtml . Это  Razor Page, а не MVC Razor View,  отличий немного. У него есть файл представления с расширением .cshtml, а для обработки серверной части у него есть файл C# с расширением .cshtml.cs (как у нас было на старой странице веб-формы .aspx).

Серверная часть содержит две основные функции  OnGetAsync и  OnPostAsync обрабатывает запросы GET и POST соответственно. Внутри регистрационного бэкенда мы могли видеть  InputModel разработку регистрационной формы. Мы должны обновить это для добавления свойств для имени и фамилии.

public class InputModel
{

    [Required]
    [DataType(DataType.Text)]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [DataType(DataType.Text)]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    ...
}

Чтобы сохранить значения этих свойств в соответствующей таблице AspNetUsers, обновите  OnPostAsync сохраните имя и фамилию в  ApplicationUser экземпляре перед вставкой в ​​таблицу.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
  ...
  var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email,
                        FirstName = Input.FirstName, LastName = Input.LastName };
  var result = await _userManager.CreateAsync(user, Input.Password);
  ...
}

Теперь давайте обновим файл razor следующим образом.

@page
@model RegisterModel

@{ ViewData["Title"] = "Register"; }

@{ Layout = "~/Areas/Identity/Pages/_AuthLayout.cshtml"; }

<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.FirstName"></label>
                <input asp-for="Input.FirstName" class="form-control" />
                <span asp-validation-for="Input.FirstName" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.LastName"></label>
                <input asp-for="Input.LastName" class="form-control" />
                <span asp-validation-for="Input.LastName" class="text-danger"></span>
            </div>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="Input.Email"></label>
        <input asp-for="Input.Email" class="form-control" />
        <span asp-validation-for="Input.Email" class="text-danger"></span>
    </div>
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.Password"></label>
                <input asp-for="Input.Password" class="form-control" />
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.ConfirmPassword"></label>
                <input asp-for="Input.ConfirmPassword" class="form-control" />
                <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
            </div>
        </div>
    </div>
    <button type="submit" class="btn btn-primary">Register</button>
</form>

@section Scripts {
    <partial name="_ValidationScriptsPartial" ></partial>
}

Я установил макет  _AuthLayout.cshtml  и добавил элементы управления формой для имени и фамилии. Теперь, если вы перейдете по URL-адресу  /Identity/Account/Register, вы увидите следующую форму регистрации пользователя.

Если вы попытаетесь отправить регистрационную форму, вы увидите, что по умолчанию Identity API применяет некоторые проверки к элементам управления формы. вы можете переопределить их следующим образом в  /Areas/Identity/IdentityHostingStartup.cs .

public class IdentityHostingStartup : IHostingStartup
{
    public void Configure(IWebHostBuilder builder)
    {
           ...

            services.AddDefaultIdentity<ApplicationUser>(options => {
                options.Password.RequireLowercase = false;
                options.Password.RequireUppercase = false;
                options.SignIn.RequireConfirmedAccount = false;
            })
                .AddEntityFrameworkStores<AuthDbContext>();
        });
    }
}

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

Форма входа

Аутентификация пользователя или вход в систему обрабатываются в /Areas/Identity/Pages/Account/Login.cshtml. Теперь вы можете обновить файл Razor, как показано ниже.

@page
@model LoginModel

@{ViewData["Title"] = "Login";}


@{
    Layout = "~/Areas/Identity/Pages/_AuthLayout.cshtml";
}
<div class="col-md-10 offset-1">
    <div class="login-form-icon">
        <i class="fas fa-user-circle fa-9x text-secondary"></i>
    </div>
    <form id="account" method="post">
        <div asp-validation-summary="All" class="text-danger"></div>
        <div class="form-group">
            <div class="input-group">
                <div class="input-group-prepend">
                    <div class="input-group-text">
                        <i class="fas fa-envelope"></i>
                    </div>
                </div>
                <input asp-for="Input.Email" class="form-control" placeholder="Email Address" />
            </div>
            <span asp-validation-for="Input.Email" class="text-danger"></span>
        </div>
        <div class="form-group">
            <div class="input-group">
                <div class="input-group-prepend">
                    <div class="input-group-text">
                        <i class="fas fa-lock"></i>
                    </div>
                </div>
                <input asp-for="Input.Password" class="form-control" placeholder="Password" />
            </div>
            <span asp-validation-for="Input.Password" class="text-danger"></span>
        </div>
        <div class="form-group">
            <div class="checkbox">
                <label asp-for="Input.RememberMe">
                    <input asp-for="Input.RememberMe" />
                    @Html.DisplayNameFor(m => m.Input.RememberMe)
                </label>
            </div>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary btn-block">Log in</button>
        </div>
    </form>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" ></partial>
}

Теперь форма входа должна выглядеть так.

Наконец, если вы хотите перенаправить уже вошедшего в систему пользователя обратно на домашнюю страницу со страницы входа или регистрации, вам просто нужно обновить  onGetAsync метод с помощью следующих операторов if как на странице входа, так и на странице регистрации.

public async Task OnGetAsync(string returnUrl = null)
{
    if (User.Identity.IsAuthenticated)
    {
        Response.Redirect("/Home");
    }

    ...
}

Наконец, вы можете защитить контроллеры или действия от несанкционированного запроса с помощью  Authorize атрибута. Если будет сделан какой-либо несанкционированный запрос, пользователь будет перенаправлен на страницу входа. Я сделал то же самое в  HomeController.

[Authorize]
public class HomeController : Controller
{ ... }

Следующий шаг

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

  • подтверждение электронного адреса
  • Забыл пароль
  • JWT-аутентификация
  • Добавьте внешнюю аутентификацию, такую ​​как Facebook, Google и т. д.

Все это будет описано в других статьях.