Creare un meccanismo di accesso utilizzando l'autenticazione tramite cookie e creare un meccanismo da reindirizzare se non si è autenticati

Pagina aggiornata :
Data di creazione della pagina :

Ambiente operativo

Visual Studio
  • Comunità di Visual Studio 2022
ASP.NET Core (MVC, Razor Pages)
6.0

Dapprima

Questa volta, ASP.NET Core utilizzerà l'autenticazione dei cookie come meccanismo di autenticazione dell'accesso. È possibile pensare all'autenticazione dei cookie come simile all'autenticazione basata su form tradizionale.

Un altro meccanismo di autenticazione per ASP.NET Core è ASP.NET Core Identity. Oltre all'autenticazione tramite moduli, consente di autenticarsi con API, utilizzare servizi di accesso esterni, gestire e reimpostare le password, ecc. È possibile utilizzare molte funzionalità. Tuttavia, dal punto di vista della semplice creazione di una semplice schermata di accesso questa volta, si tratterà di un meccanismo di autenticazione un po' esagerato. Questa volta non lo useremo.

Nei suggerimenti per l'autenticazione dei cookie introdotti questa volta, non è possibile visualizzare nient'altro che la schermata di accesso a meno che non si effettui l'accesso. Se provi a navigare in un'altra schermata, verrai reindirizzato alla schermata di accesso. Se si effettua l'accesso, è possibile visualizzare altre schermate.

Per il momento, è possibile accedere inserendo il nome utente e la password nella schermata di accesso. L'autenticazione dell'utente viene implementata come luogo temporaneo. In questo caso, l'obiettivo principale è l'implementazione dell'autenticazione dei cookie, quindi l'essenza del processo di determinazione, ad esempio se la password è corretta, non è l'essenza.

Questo suggerimento descrive solo una parte del programma. Per il codice completo, scarica il programma completo. Vengono inoltre illustrati i framework MVC e Razor Pages.

Creare un progetto

Avviare Visual Studio e creare un nuovo progetto.

Per Razor Pages selezionare ASP.NET app Web di base o per MVC selezionare ASP.NET app Web di base (Model-View-Controller).

Specificare un nome di progetto a scelta e una posizione per il progetto.

Per il tipo di autenticazione, selezionare "Nessuna". Se si sceglie un'altra autenticazione, si userà ASP.NET identità di base. Quando hai finito con le impostazioni, fai clic sul pulsante "Crea".

Dopo aver creato il progetto, durante l'esecuzione del debug verrà visualizzata la schermata mostrata di seguito. Creeremo un programma basato su questa schermata.

Edit Program.cs (Razor Pages, MVC Common)

Aggiungere le definizioni necessarie per l'autenticazione dei cookie a Program.cs. Gli spazi dei nomi da aggiungere sono i seguenti:

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

Di seguito è builder.Services riportato il codice da aggiungere a .

// === 省略 ===

// 「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 È possibile abilitare l'autenticazione dei cookie eseguendo il metodo and. Se non è necessario modificare il nome dello schema, CookieAuthenticationDefaults.AuthenticationScheme specificare .

AddAuthorization Se si options.FallbackPolicy RequireAuthenticatedUser specifica il metodo È possibile applicare un criterio di autenticazione richiesto a tutte le pagine, a tutti i controller e alle azioni. Se si desidera richiedere l'autenticazione per qualcosa di diverso dalla schermata di accesso, è un metodo utile in termini di riduzione del codice e prevenzione di errori nella descrizione. Sarà necessario scrivere separatamente il codice che non richiede l'autenticazione per la schermata di accesso.

Di seguito è app riportato il codice per .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Poiché si desidera aggiungere la funzionalità di autenticazione all'applicazione, app.UseAuthentication() verrà aggiunto . La posizione della descrizione è conforme alla documentazione MSDN, app. UseAuthorization(). A parte questo, è ancora un modello.

Programmi per i progetti Razor Pages

Creare una pagina di accesso (Pages/Account/Login.cshtml.cs)

Creare un file

Crea una pagina di accesso. Il percorso del file deve essere creato come "/Pages/Account/Login.cshtml". Questo perché il percorso di accesso predefinito è così. Se si desidera modificare questo percorso, è possibile Program.cs farlo impostando l'argomento AddCookie del metodo di .

Puoi crearlo copiando altri file invece di crearlo dal menu, ma in tal caso, correggi correttamente il programma.

Consenti agli utenti di accedere alla pagina di login senza effettuare il login

Program.cs Poiché è possibile accedere a tutte le pagine solo dopo aver effettuato l'accesso, è necessario impostare solo la pagina di accesso in modo da potervi accedere anche se non si è loggati.

AllowAnonymous Aggiungendo attributi, è possibile accedere alla pagina di destinazione anche se non è autenticata. AllowAnonymous Gli attributi possono essere utilizzati in altre posizioni diverse dalla schermata di accesso, ad esempio operazioni API non correlate all'autenticazione dei 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
  {
  }
}

Creare una variabile per ricevere l'input

Quando effettui l'accesso, dichiari che il tuo nome utente è in grado di ricevere quei valori perché inserisci la tua password.

// 省略

[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; } = "";
}

Definire un nome utente e una password per l'autenticazione dell'accesso

Originariamente, sarebbe stato archiviato in un database, ecc., ma poiché il giudizio dell'utente non è l'obiettivo principale questa volta, lo farò come luogo temporaneo.

// 省略

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

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

Processo di accesso

/// <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");
}

Questo è il processo di autenticazione dopo aver premuto il pulsante di accesso. Se il nome utente e la password corrispondono, è possibile eseguire l'autenticazione.

Il codice descritto è il codice minimo richiesto per l'autenticazioneClaimClaimsIdentityClaimsPrincipal e HttpContext.SignInAsync Chiamando il metodo, viene generato e autenticato un cookie.

Se sono necessarie attestazioni aggiuntive o è necessaria la scadenza del cookie, vengono aggiunti parametri aggiuntivi.

Dopo aver effettuato l'accesso, si viene reindirizzati a , dove /Index è richiesta l'autenticazione.

Processo di disconnessione

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

Logout Quando si accede con un gestore, viene elaborato per disconnettersi. HttpContext.SignOutAsync Chiamando il metodo, è possibile eliminare il cookie e riportarlo a uno stato in cui non si è effettuato l'accesso.

Creazione di una vista

Non prendiamo in considerazione l'aspetto. Aggiungi i campi per inserire il tuo nome utente e password come mostrato di seguito e posiziona un pulsante per accedere. Dovresti anche avere un link per accedere senza effettuare il login per /Index il test.

Poiché è problematico inserire il nome utente e la password, viene impostato il valore iniziale.

@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"); }
}

Creare un collegamento di disconnessione (/Pages/Shared/_Layout.cshtml)

Non apporteremo alcuna modifica alla schermata iniziale, ma inseriremo un link di disconnessione nella barra di navigazione. Inoltre, per il test, pubblica un link che ti porti alla schermata di accesso senza disconnetterti.

<!-- 中略 -->
<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>
<!-- 中略 -->

Questo è tutto per il codice di Razor Pages.

Programmi per progetti MVC

Creazione di un modello di accesso

È stato creato un modello per ricevere i valori immessi nella schermata di accesso.

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; } = "";
  }
}

Creazione di un AccountController

Creare i controller e le azioni necessarie per creare la schermata di accesso. Creare il nome AccountController del controller come . Questo perché, per impostazione predefinita, il nome del controller e il nome dell'azione nella schermata di accesso sono impostati su "~/Account/Login". Se si desidera modificare questo percorso, è possibile farlo nelle opzioni del AddCookie metodo in Program.cs. Per ora, procederemo con le impostazioni predefinite.

Innanzitutto, creiamo il lato Controller.

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 Concedendo l'attributo, tutte le azioni in esso contenute possono essere eseguite senza essere autenticate. In questo modo è possibile accedere solo alla schermata di accesso senza autenticazione.

AllowAnonymous Gli attributi possono essere utilizzati anche nei controller solo API che non sono correlati all'autenticazione dei cookie in altre posizioni diverse dalla schermata di accesso.

Successivamente, definisci gli utenti e le password che possono accedere. Originariamente, sarebbe stato archiviato in un database, ecc., ma poiché il giudizio dell'utente non è l'obiettivo principale questa volta, lo farò come luogo temporaneo.

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

Di seguito è riportata un'azione che visualizza la schermata di accesso. Poiché viene solo visualizzata, restituisce la vista così com'è.

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

Di seguito è riportato il codice da elaborare al momento dell'accesso.

/// <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");
}

Questo è il processo di autenticazione dopo aver premuto il pulsante di accesso. Se il nome utente e la password corrispondono, è possibile eseguire l'autenticazione.

Il codice descritto è il codice minimo richiesto per l'autenticazioneClaimClaimsIdentityClaimsPrincipal e HttpContext.SignInAsync Chiamando il metodo, viene generato e autenticato un cookie.

Se sono necessarie attestazioni aggiuntive o è necessaria la scadenza del cookie, vengono aggiunti parametri aggiuntivi.

Dopo aver effettuato l'accesso, si viene reindirizzati a , dove ~/Home/Index è richiesta l'autenticazione.

Infine, viene aggiunto il processo di logout.

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

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

HttpContext.SignOutAsync Chiamando il metodo, è possibile eliminare il cookie e riportarlo a uno stato in cui non si è effettuato l'accesso.

Creare una visualizzazione (modulo di accesso) (/Views/Account/Login.cshtml)

Login Fare clic con il pulsante destro del mouse sull'azione per aggiungere una vista. Puoi anche crearlo copiandolo da un altro file.

Non prendiamo in considerazione l'aspetto. Aggiungi i campi per inserire il tuo nome utente e password come mostrato di seguito e posiziona un pulsante per accedere. Dovresti anche avere un link per accedere senza effettuare il login per Home/Index il test.

Poiché è problematico inserire il nome utente e la password, viene impostato il valore iniziale.

@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"); }
}

Creare un collegamento di disconnessione (/Views/Shared/_Layout.cshtml)

Non apporteremo alcuna modifica alla schermata iniziale, ma inseriremo un link di disconnessione nella barra di navigazione. Inoltre, per il test, pubblica un link che ti porti alla schermata di accesso senza disconnetterti.

<!-- 中略 -->
<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>
<!-- 中略 -->

Questo è tutto per il codice MVC.

Conferma dell'operazione

In questo modo si completa l'implementazione minima richiesta per l'autenticazione dei cookie. Prova a eseguirlo e vedi come funziona. Il comportamento dovrebbe cambiare a seconda che tu abbia effettuato l'accesso o meno. Come semplice esempio, è possibile vedere il comportamento seguente.

Risultato dell'operazione ⇒ dell'operazione
Torna a casa senza effettuare l'accesso Reindirizzamento alla schermata di accesso
accesso Vai alla schermata iniziale
Esci di casa e torna a casa senza effettuare l'accesso Reindirizzamento alla schermata di accesso
Torna a casa senza disconnetterti da casa e accedere Vai alla schermata iniziale