Creați un mecanism de conectare utilizând autentificarea cu cookie-uri și creați un mecanism pentru a fi redirecționat dacă nu sunteți autentificat

Pagina actualizată :
Data creării paginii :

Mediu de operare

Visual Studio
  • Comunitatea Visual Studio 2022
ASP.NET Core (MVC, Razor Pages)
6.0

La început

De data aceasta, ASP.NET Core va folosi autentificarea cookie-urilor ca mecanism de autentificare prin autentificare. Vă puteți gândi la autentificarea cookie-urilor ca fiind similară cu autentificarea formularelor tradiționale.

Un alt mecanism de autentificare pentru ASP.NET Core este ASP.NET Core Identity. În plus față de autentificarea utilizând formulare, acest lucru vă permite să vă autentificați cu API-uri, să utilizați servicii de conectare externe, să gestionați și să resetați parolele etc. Puteți utiliza o mulțime de funcții. Cu toate acestea, din punctul de vedere al creării unui simplu ecran de conectare de data aceasta, va fi un mecanism de autentificare oarecum exagerat. Nu o vom folosi de data aceasta.

În sfaturile de autentificare a cookie-urilor introduse de această dată, nu puteți afișa altceva decât ecranul de conectare decât dacă vă conectați. Dacă încercați să navigați la un alt ecran, veți fi redirecționat către ecranul de conectare. Dacă vă conectați, puteți vizualiza alte ecrane.

Pentru moment, vă puteți conecta introducând numele de utilizator și parola pe ecranul de conectare. Autentificarea utilizatorului în sine este implementată ca un loc temporar. În acest caz, accentul principal este pus pe implementarea autentificării cookie-urilor, astfel încât esența procesului de determinare, cum ar fi dacă parola este corectă, nu este esența.

Acest sfat descrie doar o parte a programului. Pentru codul complet, descărcați programul complet. De asemenea, acoperă atât cadrele MVC, cât și Razor Pages.

Crearea unui proiect

Porniți Visual Studio și creați un proiect nou.

Pentru Razor Pages, selectați ASP.NET Core Web App sau, pentru MVC, selectați ASP.NET Core Web App (Model-View-Controller).

Specificați un nume de proiect la alegere și o locație pentru proiect.

Pentru tipul de autentificare, selectați "Niciunul". Dacă alegeți altă autentificare, veți utiliza ASP.NET identitate de bază. Când ați terminat setările, faceți clic pe butonul "Creați".

După crearea proiectului, ecranul prezentat mai jos va fi afișat la executarea depanării. Vom crea un program bazat pe acest ecran.

Editare program.cs (Razor Pages, MVC Common)

Adăugați definițiile necesare pentru autentificarea cookie-urilor la Program.cs. Spațiile de nume care trebuie adăugate sunt următoarele:

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

builder.Services Iată codul de adăugat la .

// === 省略 ===

// 「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 Puteți activa autentificarea cookie-urilor executând metoda și. Dacă nu trebuie să modificați numele schemei, CookieAuthenticationDefaults.AuthenticationScheme specificați .

AddAuthorization Dacă specificați options.FallbackPolicy RequireAuthenticatedUser pentru metodă Puteți aplica o politică necesară autentificării pentru toate paginile, toate controlerele și acțiunile. Dacă doriți să solicitați autentificarea pentru altceva decât ecranul de conectare, este o metodă utilă în ceea ce privește reducerea codului și prevenirea erorilor din descriere. Va trebui să scrieți separat codul care nu necesită autentificare pentru ecranul de conectare.

Următorul este app codul pentru .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Deoarece dorim să adăugăm funcționalitate de autentificare aplicației, app.UseAuthentication() vom adăuga . Locația descrierii este conform documentației MSDN, aplicației. UseAuthorization(). În afară de asta, este încă un șablon.

Programe pentru proiecte Razor Pages

Creați o pagină de conectare (Pages/Account/Login.cshtml.cs)

Crearea unui fișier

Creați o pagină de conectare. Calea fișierului trebuie creată ca "/Pages/Account/Login.cshtml". Acest lucru se datorează faptului că calea implicită de conectare este așa. Dacă doriți să modificați această cale, puteți Program.cs face acest lucru setând argumentul AddCookie metodei .

Puteți să-l creați copiind alte fișiere în loc să îl creați din meniu, dar în acest caz, vă rugăm să remediați corect programul.

Permiteți utilizatorilor să acceseze pagina de conectare fără a se conecta

Program.cs Deoarece toate paginile pot fi accesate numai atunci când sunteți conectat, trebuie să setați doar pagina de conectare, astfel încât să o puteți accesa chiar dacă nu sunteți conectat.

AllowAnonymous Prin adăugarea de atribute, pagina țintă poate fi accesată chiar dacă nu este autentificată. AllowAnonymous Atributele pot fi utilizate în alte locuri decât ecranul de conectare, cum ar fi operațiunile API care nu au legătură cu autentificarea cookie-urilor.

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
  {
  }
}

Crearea unei variabile pentru a primi date de intrare

Când vă conectați, vă declarați numele de utilizator pentru a putea primi aceste valori, deoarece introduceți parola.

// 省略

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

Definiți un nume de utilizator și o parolă pentru autentificarea de conectare

Inițial, ar fi stocat într-o bază de date etc., dar din moment ce judecata utilizatorului nu este principalul obiectiv de data aceasta, îl voi face ca un loc temporar.

// 省略

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

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

Procesul de conectare

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

Acesta este procesul de autentificare după apăsarea butonului de conectare. Dacă numele de utilizator și parola se potrivesc, autentificarea este posibilă.

Codul descris este codul minim necesar pentru autentificareClaimClaimsIdentityClaimsPrincipal și HttpContext.SignInAsync Prin apelarea metodei, un cookie este generat și autentificat.

Dacă sunt necesare revendicări suplimentare sau este necesară expirarea cookie-urilor, se adaugă parametri suplimentari.

După conectare, sunteți redirecționat către , unde /Index este necesară autentificarea.

Procesul de deconectare

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

Logout Când este accesat cu un handler, acesta este procesat pentru a vă deconecta. HttpContext.SignOutAsync Prin apelarea metodei, puteți șterge cookie-ul și îl puteți readuce într-o stare în care nu sunteți conectat.

Crearea unei vizualizări

Nu luăm în considerare aspectul. Adăugați câmpuri pentru introducerea numelui de utilizator și a parolei așa cum se arată mai jos și plasați un buton pentru a vă conecta. De asemenea, ar trebui să aveți un link pentru a accesa fără a vă conecta pentru /Index testare.

Deoarece este dificil să introduceți numele de utilizator și parola, valoarea inițială este setată.

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

Crearea unui link de deconectare (/Pages/Shared/_Layout.cshtml)

Nu vom face modificări la ecranul de pornire, dar vom pune un link de deconectare în bara de navigare. De asemenea, pentru testare, postați un link care vă duce la ecranul de conectare fără a vă deconecta.

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

Asta e pentru codul Razor Pages.

Programe pentru proiecte MVC

Crearea unui model de conectare

Ați creat un model pentru a primi valorile introduse pe ecranul de conectare.

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

Crearea unui AccountController

Creați controlerele și acțiunile necesare pentru a crea ecranul de conectare. Creați numele AccountController controlerului ca . Acest lucru se datorează faptului că, în mod implicit, numele controlerului și numele acțiunii din ecranul de conectare sunt setate la "~/Account/Login". Dacă doriți să modificați această cale, puteți face acest lucru în opțiunile AddCookie metodei din Program.cs. Deocamdată, vom continua cu setările implicite.

Mai întâi, să creăm partea controlerului.

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 Prin acordarea atributului, toate acțiunile din acesta pot fi efectuate fără a fi autentificate. Acest lucru vă permite să accesați numai ecranul de conectare fără autentificare.

AllowAnonymous Atributele pot fi, de asemenea, utilizate în controlere numai API care nu sunt legate de autentificarea cookie-urilor în alte locuri decât ecranul de conectare.

Apoi, definiți utilizatorii și parolele care se pot conecta. Inițial, ar fi stocat într-o bază de date etc., dar din moment ce judecata utilizatorului nu este principalul obiectiv de data aceasta, îl voi face ca un loc temporar.

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

Următoarea este o acțiune care afișează ecranul de conectare. Deoarece este doar afișat, returnează vizualizarea așa cum este.

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

Mai jos este codul care trebuie procesat la conectare.

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

Acesta este procesul de autentificare după apăsarea butonului de conectare. Dacă numele de utilizator și parola se potrivesc, autentificarea este posibilă.

Codul descris este codul minim necesar pentru autentificareClaimClaimsIdentityClaimsPrincipal și HttpContext.SignInAsync Prin apelarea metodei, un cookie este generat și autentificat.

Dacă sunt necesare revendicări suplimentare sau este necesară expirarea cookie-urilor, se adaugă parametri suplimentari.

După conectare, sunteți redirecționat către , unde ~/Home/Index este necesară autentificarea.

În cele din urmă, se adaugă procesul de deconectare.

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

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

HttpContext.SignOutAsync Prin apelarea metodei, puteți șterge cookie-ul și îl puteți readuce într-o stare în care nu sunteți conectat.

Crearea unei vizualizări (formular de conectare) (/Views/Account/Login.cshtml)

Login Faceți clic dreapta pe acțiune pentru a adăuga o vizualizare. De asemenea, îl puteți crea copiindu-l dintr-un alt fișier.

Nu luăm în considerare aspectul. Adăugați câmpuri pentru introducerea numelui de utilizator și a parolei așa cum se arată mai jos și plasați un buton pentru a vă conecta. De asemenea, ar trebui să aveți un link pentru a accesa fără a vă conecta pentru Home/Index testare.

Deoarece este dificil să introduceți numele de utilizator și parola, valoarea inițială este setată.

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

Crearea unui link de deconectare (/Views/Shared/_Layout.cshtml)

Nu vom face modificări la ecranul de pornire, dar vom pune un link de deconectare în bara de navigare. De asemenea, pentru testare, postați un link care vă duce la ecranul de conectare fără a vă deconecta.

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

Asta e pentru codul MVC.

Confirmarea funcționării

Aceasta finalizează implementarea minimă necesară a autentificării cookie-urilor. Încercați să-l rulați și vedeți cum funcționează. Comportamentul ar trebui să se schimbe în funcție de faptul dacă sunteți conectat sau nu. Ca exemplu simplu, puteți vedea următorul comportament.

operației
Rezultatul operațiunii
Du-te acasă fără să te conectezi Redirecționați către ecranul de conectare
Login Accesați ecranul de pornire
Deconectați-vă de acasă și mergeți acasă fără să vă conectați Redirecționați către ecranul de conectare
Du-te acasă fără să te deconectezi de acasă și să te conectezi Accesați ecranul de pornire