Створіть механізм входу за допомогою автентифікації файлів 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. Коли ви закінчите з налаштуваннями, натисніть кнопку «Створити».

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

Програма редагування.cs (Бритвені сторінки, MVC Common)

Додайте визначення, необхідні для автентифікації файлів cookie, до Програми.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, додаток. 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 контролера як . Це пов'язано з тим, що за замовчуванням ім'я контролера та ім'я дії на екрані входу встановлено у значення "~/Обліковий запис/Вхід". Якщо ви хочете змінити цей шлях, ви можете зробити це в опціях AddCookie методу в Програма.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 завершена. Спробуйте запустити його і подивіться, як він працює. Поведінка повинна змінюватися в залежності від того, увійшли ви в систему чи ні. Як простий приклад можна побачити наступну поведінку.

Операція результат операції
Ідіть додому, не входячи в систему Перенаправлення на екран входу
Логін Перейдіть на головний екран
Вийдіть з дому та йдіть додому, не входячи в систему Перенаправлення на екран входу
Ідіть додому, не виходячи з дому та не входячи в систему Перейдіть на головний екран