Создайте механизм входа в систему с помощью проверки подлинности файлов cookie и создайте механизм перенаправления, если вы не прошли проверку подлинности

Страница обновлена :
Дата создания страницы :

Условия эксплуатации

Визуальная студия
  • Сообщество Visual Studio 2022
ASP.NET Core (MVC, Razor Pages)
6.0

Сначала

На этот раз ASP.NET Core будет использовать аутентификацию с помощью файлов cookie в качестве механизма аутентификации при входе в систему. Вы можете думать о проверке подлинности файлов cookie как о чем-то похожем на традиционную аутентификацию форм.

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

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

На данный момент вы можете войти в систему, введя свое имя пользователя и пароль на экране входа в систему. Сама аутентификация пользователя реализована как временное место. В этом случае основное внимание уделяется реализации аутентификации с помощью файлов cookie, поэтому суть процесса определения, например, правильность пароля, не является сутью.

В этом совете описывается только часть программы. Чтобы получить полный код, загрузите полную программу. Он также охватывает фреймворки MVC и Razor Pages.

Создание проекта

Запустите Visual Studio и создайте новый проект.

Для Razor Pages выберите ASP.NET Core Web App, а для MVC выберите ASP.NET Core Web App (Model-View-Controller).

Укажите имя проекта по вашему выбору и местоположение для проекта.

В качестве типа аутентификации выберите «Нет». Если вы выберете другую проверку подлинности, вы будете использовать ASP.NET Core Identity. Когда вы закончите с настройками, нажмите кнопку «Создать».

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

Редактирование Program.cs (Razor Pages, MVC Common)

Добавьте определения, необходимые для проверки подлинности файлов cookie, в Program.cs. Необходимо добавить следующие пространства имен:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;

Ниже builder.Services приведен код, который можно добавить в .

// === 省略 ===

// 「Razor Pages」のコード
// builder.Services.AddRazorPages();
// 「MVC」のコード
// builder.Services.AddControllersWithViews();

// ※ここから追加

// Cookie による認証スキームを追加する
builder.Services
  .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie();

builder.Services.AddAuthorization(options =>
{
  // AllowAnonymous 属性が指定されていないすべての画面、アクションなどに対してユーザー認証が必要となる
  options.FallbackPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();
});

// ※ここまで追加

var app = builder.Build();

// === 省略 ===

AddAuthenticationAddCookie Вы можете включить аутентификацию файлов cookie, выполнив метод and. Если вам не нужно менять название схемы, CookieAuthenticationDefaults.AuthenticationScheme укажите .

AddAuthorization Если вы укажете options.FallbackPolicy RequireAuthenticatedUser для метода Вы можете применить политику, требующую проверки подлинности, ко всем страницам, всем контроллерам и действиям. Если вы хотите требовать аутентификацию для чего-либо, кроме экрана входа в систему, это полезный метод с точки зрения сокращения кода и предотвращения ошибок в описании. Код, не требующий аутентификации, для экрана входа в систему придется писать отдельно.

Ниже приведен app код для .

// === 省略 ===

app.UseRouting();

app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可

// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
//     name: "default",
//     pattern: "{controller=Home}/{action=Index}/{id?}");

// === 省略 ===

Поскольку мы хотим добавить в приложение функциональность аутентификации, app.UseAuthentication() мы добавим . Описание местоположения соответствует документации MSDN, app. UseAuthorization(). В остальном это все еще шаблон.

Программы для проектов Razor Pages

Создайте страницу входа (Pages/Account/Login.cshtml.cs)

Создание файла

Создайте страницу входа. Путь к файлу должен быть создан в виде "/Pages/Account/Login.cshtml". Это связано с тем, что путь входа по умолчанию выглядит следующим образом. Если вы хотите изменить этот путь, вы Program.cs можете сделать это, установив аргумент AddCookie метода .

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

Разрешить пользователям доступ к странице входа без входа в систему

Program.cs Поскольку доступ ко всем страницам возможен, только когда вы вошли в систему, вам необходимо установить только страницу входа, чтобы вы могли получить к ней доступ, даже если вы не вошли в систему.

AllowAnonymous Добавив атрибуты, можно получить доступ к целевой странице, даже если она не аутентифицирована. AllowAnonymous Атрибуты могут использоваться в других местах, кроме экрана входа в систему, например, в операциях API, не связанных с аутентификацией файлов cookie.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;

namespace AspNetCoreCookieAuthenticationRazorPages.Pages.Account
{
  [AllowAnonymous]
  public class LoginModel : PageModel
  {
  }
}

Создание переменной для получения входных данных

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

// 省略

[AllowAnonymous]
public class LoginModel : PageModel
{
  /// <summary>ユーザー名。</summary>
  [BindProperty]
  [Required]
  [DisplayName("ユーザー名")]
  public string UserName { get; set; } = "";

  /// <summary>パスワード。</summary>
  [BindProperty]
  [Required]
  [DataType(DataType.Password)]
  [DisplayName("パスワード")]
  public string Password { get; set; } = "";
}

Определение имени пользователя и пароля для аутентификации при входе в систему

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

// 省略

[AllowAnonymous]
public class LoginModel : PageModel
{
  // 省略

  /// <summary>仮のユーザーデータベースとする。</summary>
  private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };
}

Процесс входа в систему

/// <summary>ログイン処理。</summary>
public async Task<ActionResult> OnPost()
{
  // 入力内容にエラーがある場合は処理を中断してエラー表示
  if (ModelState.IsValid == false) return Page();

  // ユーザーの存在チェックとパスワードチェック (仮実装)
  // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
  if (UserAccounts.TryGetValue(UserName, out string? getPass) == false || Password != getPass)
  {
    ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
    return Page();
  }

  // サインインに必要なプリンシパルを作る
  var claims = new[] { new Claim(ClaimTypes.Name, UserName) };
  var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync(principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToPage("/Index");
}

Это процесс аутентификации после нажатия кнопки входа. Если имя пользователя и пароль совпадают, аутентификация возможна.

Описанный код является минимальным кодом, необходимым для проверки подлинности,ClaimClaimsIdentityClaimsPrincipal и HttpContext.SignInAsync При вызове метода генерируется и аутентифицируется файл cookie.

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

После входа в систему вы будете перенаправлены на сайт , где /Index требуется аутентификация.

Процесс выхода из системы

/// <summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
  // 認証クッキーをレスポンスから削除
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}

Logout При доступе с помощью обработчика он обрабатывается для выхода из системы. HttpContext.SignOutAsync Вызвав метод, вы можете удалить файл cookie и вернуть его в состояние, в котором вы не вошли в систему.

Создание представления

Мы не учитываем внешний вид. Добавьте поля для ввода логина и пароля, как показано ниже, и разместите кнопку для входа. У вас также должна быть ссылка для доступа без входа в систему для /Index тестирования.

Так как вводить имя пользователя и пароль хлопотно, устанавливается начальное значение.

@page
@model AspNetCoreCookieAuthenticationRazorPages.Pages.Account.LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-page="/Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Создание ссылки для выхода (/Pages/Shared/_Layout.cshtml)

Мы не будем вносить никаких изменений на главный экран, но разместим ссылку для выхода на панели навигации. Кроме того, для тестирования разместите ссылку, которая приведет вас на экран входа без выхода из системы.

<!-- 中略 -->
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
  <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
    </li>
    <!-- ここから追加 -->
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/Login" asp-page-handler="Logout">ログアウト</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/Login">ログアウトせずログインへ</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

Вот и все для кода Razor Pages.

Программы для MVC-проектов

Создание модели входа в систему

Вы создали модель для получения значений, введенных на экране входа в систему.

namespace AspNetCoreCookieAuthenticationMvc.Models
{
  public class LoginModel
  {
    /// <summary>ユーザー名。</summary>
    [Required]
    [DisplayName("ユーザー名")]
    public string UserName { get; set; } = "";

    /// <summary>パスワード。</summary>
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("パスワード")]
    public string Password { get; set; } = "";
  }
}

Создание AccountController

Создайте контроллеры и действия, необходимые для создания экрана входа. Создайте имя AccountController контроллера как . Это связано с тем, что по умолчанию имя контроллера и имя действия на экране входа в систему установлены в "~/Account/Login". Если вы хотите изменить этот путь, вы можете сделать это в параметрах AddCookie метода в Program.cs. А пока мы продолжим с настройками по умолчанию.

Во-первых, давайте создадим сторону контроллера.

using AspNetCoreCookieAuthenticationMvc.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace AspNetCoreCookieAuthenticationMvc.Controllers
{
  /// <remarks>
  /// <see cref="AllowAnonymous"/> 属性は Cookie 認証していなくてもアクセスできる Action (Controller) であることを示す。
  /// </remarks>
  [AllowAnonymous]
  public class AccountController : Controller
  {
  }
}

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

AllowAnonymous Атрибуты также могут использоваться в контроллерах API, которые не связаны с аутентификацией файлов cookie в других местах, кроме экрана входа в систему.

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

[AllowAnonymous]
public class AccountController : Controller
{
  /// <summary>仮のユーザーデータベースとする。</summary>
  private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };
}

Ниже приведено действие, которое отображает экран входа в систему. Так как он только отображается, он возвращает представление как есть.

/// <summary>ログイン画面を表示します。</summary>
public IActionResult Login() => View();

Ниже приведен код, который будет обработан при входе в систему.

/// <summary>ログイン処理を実行します。</summary>
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
  // 入力内容にエラーがある場合は処理を中断してエラー表示
  if (ModelState.IsValid == false) return View(model);

  // ユーザーの存在チェックとパスワードチェック (仮実装)
  // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
  if (UserAccounts.TryGetValue(model.UserName, out string? getPass) == false || model.Password != getPass)
  {
    ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
    return View(model);
  }

  // サインインに必要なプリンシパルを作る
  var claims = new[] { new Claim(ClaimTypes.Name, model.UserName) };
  var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync(principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToAction(nameof(HomeController.Index), "Home");
}

Это процесс аутентификации после нажатия кнопки входа. Если имя пользователя и пароль совпадают, аутентификация возможна.

Описанный код является минимальным кодом, необходимым для проверки подлинности,ClaimClaimsIdentityClaimsPrincipal и HttpContext.SignInAsync При вызове метода генерируется и аутентифицируется файл cookie.

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

После входа в систему вы будете перенаправлены на сайт , где ~/Home/Index требуется аутентификация.

Наконец, добавлен процесс выхода из системы.

/// <summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
  // 認証クッキーをレスポンスから削除
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

  // ログイン画面にリダイレクト
  return RedirectToAction(nameof(Login));
}

HttpContext.SignOutAsync Вызвав метод, вы можете удалить файл cookie и вернуть его в состояние, в котором вы не вошли в систему.

Создание представления (формы входа) (/Views/Account/Login.cshtml)

Login Щелкните действие правой кнопкой мыши, чтобы добавить представление. Вы также можете создать его, скопировав из другого файла.

Мы не учитываем внешний вид. Добавьте поля для ввода логина и пароля, как показано ниже, и разместите кнопку для входа. У вас также должна быть ссылка для доступа без входа в систему для Home/Index тестирования.

Так как вводить имя пользователя и пароль хлопотно, устанавливается начальное значение.

@model LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-controller="Home" asp-action="Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Создание ссылки для выхода (/Views/Shared/_Layout.cshtml)

Мы не будем вносить никаких изменений на главный экран, но разместим ссылку для выхода на панели навигации. Кроме того, для тестирования разместите ссылку, которая приведет вас на экран входа без выхода из системы.

<!-- 中略 -->
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
  <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </li>
    <!-- ここから追加 -->
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">ログアウト</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Login">ログアウトせずログインへ</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

Вот и все для MVC-кода.

Подтверждение операции

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

Операция результат операции
Идите домой, не входя в систему Редирект на экран входа в систему
логин Перейдите на главный экран
Выйдите из дома и идите домой, не входя в систему Редирект на экран входа в систему
Идите домой, не выходя из дома и не входя в систему Перейдите на главный экран