Ustvarite mehanizem za prijavo s preverjanjem pristnosti piškotkov in ustvarite mehanizem za preusmeritev, če niste avtentikirani

Stran posodobljena :
Datum ustvarjanja strani :

Delovno okolje

Visual Studio
  • Skupnost Visual Studio 2022
ASP.NET jedro (MVC, britvice)
6.0

Sprva

Tokrat bo ASP.NET Core uporabil preverjanje pristnosti piškotkov kot mehanizem preverjanja pristnosti prijave. Preverjanje pristnosti piškotkov si lahko predstavljate kot podobno tradicionalnemu preverjanju pristnosti obrazcev.

Še en mehanizem preverjanja pristnosti za ASP.NET Core je ASP.NET Core Identity. Poleg preverjanja pristnosti z uporabo obrazcev vam to omogoča preverjanje pristnosti z API-ji, uporabo zunanjih storitev prijave, upravljanje in ponastavitev gesel itd. Uporabite lahko veliko funkcij. Vendar pa bo z vidika ustvarjanja preprostega prijavnega zaslona tokrat to nekoliko pretiran mehanizem preverjanja pristnosti. Tokrat ga ne bomo uporabili.

V nasvetih za preverjanje pristnosti piškotkov, ki so bili uvedeni tokrat, ne morete prikazati ničesar drugega kot prijavni zaslon, razen če se prijavite. Če se poskusite pomakniti na drug zaslon, boste preusmerjeni na prijavni zaslon. Če se prijavite, si lahko ogledate druge zaslone.

Zaenkrat se lahko prijavite tako, da na prijavnem zaslonu vnesete svoje uporabniško ime in geslo. Sama avtentikacija uporabnika se izvaja kot začasno mesto. V tem primeru je glavni poudarek na implementaciji avtentikacije piškotkov, zato bistvo postopka določanja, na primer, ali je geslo pravilno, ni bistvo.

V tem namigu je opisan le del programa. Za celotno kodo prenesite celoten program. Zajema tudi okvire MVC in Razor Pages.

Ustvarjanje projekta

Zaženite Visual Studio in ustvarite nov projekt.

Za Razor Pages izberite ASP.NET Core Web App ali za MVC izberite ASP.NET Core Web App (Model-View-Controller).

Določite ime projekta po vaši izbiri in lokacijo projekta.

Za vrsto preverjanja pristnosti izberite »Brez«. Če izberete drugo preverjanje pristnosti, boste uporabili ASP.NET osnovno identiteto. Ko končate z nastavitvami, kliknite gumb "Ustvari".

Po ustvarjanju projekta se prikaže spodnji zaslon, ko se izvede odpravljanje napak. Na podlagi tega zaslona bomo ustvarili program.

Uredi program.cs (britvice strani, MVC pogosto)

V program dodajte definicije, potrebne za preverjanje pristnosti piškotkov.cs. Imenski prostori, ki se dodajo, so naslednji:

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

Tukaj je builder.Services koda, ki jo lahko dodate .

// === 省略 ===

// 「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 Preverjanje pristnosti piškotkov lahko omogočite tako, da izvedete metodo and. Če vam ni treba spremeniti imena sheme, CookieAuthenticationDefaults.AuthenticationScheme določite .

AddAuthorization Če določite options.FallbackPolicy RequireAuthenticatedUser metodo Pravilnik, ki zahteva preverjanje pristnosti, lahko uporabite za vse strani, vse krmilnike in dejanja. Če želite zahtevati preverjanje pristnosti za karkoli drugega kot za prijavni zaslon, je to uporabna metoda v smislu zmanjšanja kode in preprečevanja napak v opisu. Posebej boste morali napisati kodo, ki ne zahteva preverjanja pristnosti za prijavni zaslon.

V nadaljevanju je app koda za .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Ker želimo aplikaciji dodati funkcionalnost preverjanja pristnosti, app.UseAuthentication() bomo dodali . Mesto opisa je v skladu z dokumentacijo MSDN, aplikacijo. UporabaAvtorizacija(). Razen tega je še vedno predloga.

Programi za projekte Razor Pages

Ustvarite stran za prijavo (Pages/Account/Login.cshtml.cs)

Ustvarjanje datoteke

Ustvarite stran za prijavo. Pot datoteke mora biti ustvarjena kot "/Pages/Account/Login.cshtml". To je zato, ker je privzeta pot za prijavo takšna. Če želite spremeniti to pot, lahko to storite Program.cs tako, da nastavite argument AddCookie metode .

Ustvarite ga lahko tako, da kopirate druge datoteke, namesto da bi jih ustvarili iz menija, vendar v tem primeru pravilno popravite program.

Uporabnikom omogočite dostop do strani za prijavo brez prijave

Program.cs Ker je do vseh strani mogoče dostopati le, ko ste prijavljeni, morate nastaviti samo stran za prijavo, tako da lahko do nje dostopate, tudi če niste prijavljeni.

AllowAnonymous Z dodajanjem atributov lahko dostopate do ciljne strani, tudi če ni preverjena pristnost. AllowAnonymous Atributi se lahko uporabljajo tudi drugje kot na zaslonu za prijavo, kot so postopki API-ja, ki niso povezani s preverjanjem pristnosti piškotkov.

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

Ustvarjanje spremenljivke za prejemanje vnosov

Ko se prijavite, izjavite svoje uporabniško ime, da boste lahko prejeli te vrednosti, ker vnesete svoje geslo.

// 省略

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

Določite uporabniško ime in geslo za preverjanje pristnosti prijave

Prvotno bi bila shranjena v bazi podatkov itd., Ker pa presoja uporabnikov tokrat ni v središču pozornosti, jo bom naredil kot začasno mesto.

// 省略

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

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

Postopek prijave

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

To je postopek preverjanja pristnosti po pritisku na gumb za prijavo. Če se uporabniško ime in geslo ujemata, je preverjanje pristnosti možno.

Opisana koda je minimalna koda, potrebna za avtentikacijo,ClaimClaimsIdentityClaimsPrincipal in HttpContext.SignInAsync S klicem metode se ustvari piškotek in preveri pristnost.

Če so potrebni dodatni zahtevki ali je potreben potek piškotka, se dodajo dodatni parametri.

Po prijavi ste preusmerjeni na , kjer /Index je potrebno preverjanje pristnosti.

Postopek odjave

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

Logout Ko dostopate z upravljavcem, se obdela za odjavo. HttpContext.SignOutAsync S klicem na metodo lahko piškotek izbrišete in ga vrnete v stanje, v katerem niste prijavljeni.

Ustvarjanje pogleda

Videza ne upoštevamo. Dodajte polja za vnos uporabniškega imena in gesla, kot je prikazano spodaj, in postavite gumb za prijavo. Prav tako morate imeti povezavo do dostopa, ne da bi se prijavili za /Index testiranje.

Ker je vnos uporabniškega imena in gesla težaven, je nastavljena začetna vrednost.

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

Ustvarjanje povezave za odjavo (/Pages/Shared/_Layout.cshtml)

Na začetnem zaslonu ne bomo naredili nobenih sprememb, vendar bomo v navigacijsko vrstico postavili povezavo za odjavo. Za testiranje objavite tudi povezavo, ki vas popelje na prijavni zaslon, ne da bi se odjavili.

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

To je za kodo Razor Pages.

Programi za MVC projekte

Ustvarjanje modela prijave

Ustvarili ste model za prejemanje vrednosti, vnesenih na prijavni zaslon.

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

Ustvarjanje upravljavca računa

Ustvarite krmilnike in dejanja, potrebna za ustvarjanje prijavnega zaslona. Ustvarite ime AccountController krmilnika kot . To je zato, ker sta ime krmilnika in ime dejanja na prijavnem zaslonu privzeto nastavljena na "~/Account/Login". Če želite spremeniti to pot, lahko to storite v možnostih AddCookie metode v programu.cs. Za zdaj bomo nadaljevali s privzetimi nastavitvami.

Najprej ustvarimo stran krmilnika.

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 S podelitvijo atributa se lahko vsa dejanja v njem izvedejo brez preverjanja pristnosti. To vam omogoča dostop samo do prijavnega zaslona brez preverjanja pristnosti.

AllowAnonymous Atributi se lahko uporabljajo tudi v krmilnikih samo API, ki niso povezani s preverjanjem pristnosti piškotkov na drugih mestih, razen na zaslonu za prijavo.

Nato določite uporabnike in gesla, ki se lahko prijavijo. Prvotno bi bila shranjena v bazi podatkov itd., Ker pa presoja uporabnikov tokrat ni v središču pozornosti, jo bom naredil kot začasno mesto.

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

V nadaljevanju je dejanje, ki prikaže zaslon za prijavo. Ker je samo prikazan, vrne pogled takšen, kot je.

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

Spodaj je koda, ki jo je treba obdelati ob prijavi.

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

To je postopek preverjanja pristnosti po pritisku na gumb za prijavo. Če se uporabniško ime in geslo ujemata, je preverjanje pristnosti možno.

Opisana koda je minimalna koda, potrebna za avtentikacijo,ClaimClaimsIdentityClaimsPrincipal in HttpContext.SignInAsync S klicem metode se ustvari piškotek in preveri pristnost.

Če so potrebni dodatni zahtevki ali je potreben potek piškotka, se dodajo dodatni parametri.

Po prijavi ste preusmerjeni na , kjer ~/Home/Index je potrebno preverjanje pristnosti.

Na koncu se doda postopek odjave.

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

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

HttpContext.SignOutAsync S klicem na metodo lahko piškotek izbrišete in ga vrnete v stanje, v katerem niste prijavljeni.

Ustvarite pogled (obrazec za prijavo) (/Ogledi/Račun/Login.cshtml)

Login Z desno tipko miške kliknite dejanje, da dodate pogled. Ustvarite ga lahko tudi tako, da ga kopirate iz druge datoteke.

Videza ne upoštevamo. Dodajte polja za vnos uporabniškega imena in gesla, kot je prikazano spodaj, in postavite gumb za prijavo. Prav tako morate imeti povezavo do dostopa, ne da bi se prijavili za Home/Index testiranje.

Ker je vnos uporabniškega imena in gesla težaven, je nastavljena začetna vrednost.

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

Ustvarjanje povezave za odjavo (/Views/Shared/_Layout.cshtml)

Na začetnem zaslonu ne bomo naredili nobenih sprememb, vendar bomo v navigacijsko vrstico postavili povezavo za odjavo. Za testiranje objavite tudi povezavo, ki vas popelje na prijavni zaslon, ne da bi se odjavili.

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

To je za kodo MVC.

Potrditev delovanja

S tem se zaključi minimalna zahtevana implementacija preverjanja pristnosti piškotkov. Poskusite ga zagnati in si oglejte, kako deluje. Vedenje bi se moralo spreminjati glede na to, ali ste prijavljeni ali ne. Kot preprost primer lahko vidite naslednje vedenje.

delovanja
Rezultat delovanja
Pojdi domov brez prijave Preusmeri na prijavni zaslon
Prijavo Pojdite na začetni zaslon
Odjavite se od doma in pojdite domov, ne da bi se prijavili Preusmeri na prijavni zaslon
Pojdite domov, ne da bi se odjavili od doma in se prijavili Pojdite na začetni zaslon