Opret en login-mekanisme ved hjælp af cookie-godkendelse, og opret en mekanisme, der skal omdirigeres, hvis du ikke er godkendt

Side opdateret :
Dato for oprettelse af side :

Driftsmiljø

Visual Studio
  • Visual Studio-fællesskab 2022
ASP.NET Core (MVC, barberbladssider)
6.0

Først

Denne gang bruger ASP.NET Core cookie-godkendelse som login-godkendelsesmekanisme. Du kan tænke på cookie-godkendelse som svarende til traditionel formulargodkendelse.

En anden godkendelsesmekanisme for ASP.NET Core er ASP.NET Core Identity. Ud over godkendelse ved hjælp af formularer giver dette dig mulighed for at godkende med API'er, bruge eksterne login-tjenester, administrere og nulstille adgangskoder osv. Du kan bruge mange funktioner. Men fra synspunktet om bare at oprette en simpel login-skærm denne gang, vil det være en noget overdrevet godkendelsesmekanisme. Vi vil ikke bruge det denne gang.

I de cookie-godkendelsestips, der blev introduceret denne gang, kan du ikke vise andet end loginskærmen, medmindre du logger ind. Hvis du forsøger at navigere til en anden skærm, bliver du omdirigeret til loginskærmen. Hvis du logger ind, kan du se andre skærme.

Indtil videre kan du logge ind ved at indtaste dit brugernavn og din adgangskode på loginskærmen. Selve brugergodkendelsen implementeres som et midlertidigt sted. I dette tilfælde er hovedfokus på implementeringen af cookie-godkendelse, så essensen af bestemmelsesprocessen, såsom om adgangskoden er korrekt, er ikke essensen.

Dette tip beskriver kun en del af programmet. For den komplette kode skal du downloade det komplette program. Det dækker også både MVC og Razor Pages rammer.

Oprette et projekt

Start Visual Studio, og opret et nyt projekt.

For Razor Pages skal du vælge ASP.NET Core Web App, eller for MVC skal du vælge ASP.NET Core Web App (Model-View-Controller).

Angiv et projektnavn efter eget valg og en placering til projektet.

For godkendelsestypen skal du vælge "Ingen". Hvis du vælger anden godkendelse, skal du bruge ASP.NET kerneidentitet. Når du er færdig med indstillingerne, skal du klikke på knappen "Opret".

Efter oprettelse af projektet vises skærmbilledet nedenfor, når fejlfinding udføres. Vi opretter et program baseret på denne skærm.

Rediger program.cs (barberbladssider, MVC fælles)

Føj de definitioner, der kræves til cookiegodkendelse, til Program.cs. De navneområder, der skal tilføjes, er som følger:

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

Her er builder.Services koden, der skal føjes til .

// === 省略 ===

// 「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 Du kan aktivere cookiegodkendelse ved at udføre metoden and. Hvis du ikke har brug for at ændre ordningens navn, CookieAuthenticationDefaults.AuthenticationScheme skal du angive .

AddAuthorization Hvis du options.FallbackPolicy RequireAuthenticatedUser angiver metoden Du kan anvende en politik, der kræves til godkendelse, på alle sider, alle controllere og handlinger. Hvis du vil kræve godkendelse for andet end loginskærmen, er det en nyttig metode med hensyn til at reducere koden og forhindre fejl i beskrivelsen. Du bliver nødt til at skrive kode, der ikke kræver godkendelse til loginskærmen separat.

Følgende er app koden for .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Da vi vil tilføje godkendelsesfunktionalitet til applikationen, app.UseAuthentication() tilføjer vi . Beskrivelsens placering er i henhold til MSDN-dokumentationen, app. UseAuthorization(). Bortset fra det er det stadig en skabelon.

Programmer til Razor Pages-projekter

Opret en login-side (Pages/Account/Login.cshtml.cs)

Opret en fil

Opret en login-side. Filstien skal oprettes som "/Pages/Account/Login.cshtml". Dette skyldes, at standard login-stien er sådan. Hvis du vil ændre denne sti, kan du Program.cs gøre det ved at angive argumentet for AddCookie metoden til .

Du kan oprette det ved at kopiere andre filer i stedet for at oprette det fra menuen, men i så fald skal du rette programmet korrekt.

Tillad brugere at få adgang til login-siden uden at logge ind

Program.cs Da alle sider kun kan tilgås, når du er logget ind, skal du kun indstille login-siden, så du kan få adgang til den, selvom du ikke er logget ind.

AllowAnonymous Ved at tilføje attributter kan målsiden tilgås, selvom den ikke er godkendt. AllowAnonymous Attributter kan bruges andre steder end på loginskærmen, f.eks. API-handlinger, der ikke er relateret til cookiegodkendelse.

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

Oprette en variabel for at modtage input

Når du logger ind, erklærer du dit brugernavn for at kunne modtage disse værdier, fordi du indtaster din adgangskode.

// 省略

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

Definer et brugernavn og en adgangskode til logingodkendelse

Oprindeligt ville det blive gemt i en database osv., Men da brugervurdering ikke er hovedfokus denne gang, vil jeg gøre det som et midlertidigt sted.

// 省略

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

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

Login proces

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

Dette er godkendelsesprocessen efter at have trykket på login-knappen. Hvis brugernavnet og adgangskoden stemmer overens, er godkendelse mulig.

Den beskrevne kode er den minimumskode, der kræves til godkendelse,ClaimClaimsIdentityClaimsPrincipal og HttpContext.SignInAsync Ved at kalde metoden genereres og godkendes en cookie.

Hvis der kræves yderligere krav, eller cookieudløb er påkrævet, tilføjes yderligere parametre.

Når du er logget ind, omdirigeres du til , hvor /Index godkendelse er påkrævet.

Logout proces

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

Logout Når den åbnes med en handler, behandles den for at logge ud. HttpContext.SignOutAsync Ved at kalde metoden kan du slette cookien og returnere den til en tilstand, hvor du ikke er logget ind.

Oprettelse af en visning

Vi tager ikke hensyn til udseendet. Tilføj felter til indtastning af dit brugernavn og din adgangskode som vist nedenfor, og placer en knap for at logge ind. Du skal også have et link til adgang uden at logge ind til /Index test.

Da det er besværligt at indtaste brugernavn og adgangskode, indstilles startværdien.

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

Opret et logout-link (/Pages/Shared/_Layout.cshtml)

Vi foretager ingen ændringer på startskærmen, men vi sætter et logout-link i navigationslinjen. Til test skal du også sende et link, der fører dig til loginskærmen uden at logge ud.

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

Det er det for Razor Pages-koden.

Programmer til MVC-projekter

Oprettelse af en loginmodel

Du har oprettet en model til at modtage de værdier, der er indtastet på loginskærmen.

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

Oprettelse af en AccountController

Opret de controllere og handlinger, der kræves for at oprette loginskærmen. Opret controllernavnet AccountController som . Dette skyldes, at controllernavnet og handlingsnavnet på loginskærmen som standard er indstillet til "~/Konto/Login". Hvis du vil ændre denne sti, kan du gøre det i indstillingerne AddCookie for metoden i Program.cs. Indtil videre fortsætter vi med standardindstillingerne.

Lad os først oprette controllersiden.

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 Ved at tildele attributten kan alle handlinger i den udføres uden at blive godkendt. Dette giver dig kun adgang til loginskærmen uden godkendelse.

AllowAnonymous Attributter kan også bruges i controllere, der kun indeholder API, og som ikke er relateret til cookiegodkendelse andre steder end på loginskærmen.

Definer derefter de brugere og adgangskoder, der kan logge ind. Oprindeligt ville det blive gemt i en database osv., Men da brugervurdering ikke er hovedfokus denne gang, vil jeg gøre det som et midlertidigt sted.

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

Følgende er en handling, der viser loginskærmen. Da den kun vises, returnerer den visningen, som den er.

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

Nedenfor er koden, der skal behandles, når du logger ind.

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

Dette er godkendelsesprocessen efter at have trykket på login-knappen. Hvis brugernavnet og adgangskoden stemmer overens, er godkendelse mulig.

Den beskrevne kode er den minimumskode, der kræves til godkendelse,ClaimClaimsIdentityClaimsPrincipal og HttpContext.SignInAsync Ved at kalde metoden genereres og godkendes en cookie.

Hvis der kræves yderligere krav, eller cookieudløb er påkrævet, tilføjes yderligere parametre.

Når du er logget ind, omdirigeres du til , hvor ~/Home/Index godkendelse er påkrævet.

Endelig tilføjes logout-processen.

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

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

HttpContext.SignOutAsync Ved at kalde metoden kan du slette cookien og returnere den til en tilstand, hvor du ikke er logget ind.

Opret en visning (loginformular) (/Visninger/Konto/Login.cshtml)

Login Højreklik på handlingen for at tilføje en visning. Du kan også oprette det ved at kopiere det fra en anden fil.

Vi tager ikke hensyn til udseendet. Tilføj felter til indtastning af dit brugernavn og din adgangskode som vist nedenfor, og placer en knap for at logge ind. Du skal også have et link til adgang uden at logge ind til Home/Index test.

Da det er besværligt at indtaste brugernavn og adgangskode, indstilles startværdien.

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

Opret et logout-link (/Views/Shared/_Layout.cshtml)

Vi foretager ingen ændringer på startskærmen, men vi sætter et logout-link i navigationslinjen. Til test skal du også sende et link, der fører dig til loginskærmen uden at logge ud.

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

Det er det for MVC-koden.

Bekræftelse af operationen

Dette fuldender den krævede implementering af cookiegodkendelse som minimum. Prøv at køre det og se, hvordan det fungerer. Adfærden bør ændre sig afhængigt af, om du er logget ind eller ej. Som et simpelt eksempel kan du se følgende adfærd.

Operation driftsresultat
Gå hjem uden at logge ind Omdiriger til login-skærmen
Login Gå til startskærmen
Log ud af hjemmet og gå hjem uden at logge ind Omdiriger til login-skærmen
Gå hjem uden at logge ud af hjemmet og logge ind Gå til startskærmen