Vytvořte přihlašovací mechanismus pomocí ověřování pomocí souborů cookie a vytvořte mechanismus, který bude přesměrován, pokud nejste ověřeni

Stránky aktualizovány :
Datum vytvoření stránky :

Provozní prostředí

Visual Studio
  • Visual Studio Community 2022
ASP.NET jádro (MVC, Razor Pages)
6.0

Nejprve

Tentokrát bude ASP.NET Core používat ověřování pomocí souborů cookie jako mechanismus ověřování přihlášení. Ověřování pomocí souborů cookie si můžete představit jako podobné tradičnímu ověřování pomocí formulářů.

Dalším ověřovacím mechanismem pro ASP.NET Core je ASP.NET Core Identity. Kromě autentizace pomocí formulářů vám to umožňuje autentizaci pomocí API, používání externích přihlašovacích služeb, správu a resetování hesel atd. Můžete využít spoustu funkcí. Z pohledu pouhého vytvoření jednoduché přihlašovací obrazovky se však tentokrát bude jednat o poněkud přehnaný autentizační mechanismus. Tentokrát to nevyužijeme.

V tipech pro ověřování souborů cookie, které byly představeny tentokrát, nemůžete zobrazit nic jiného než přihlašovací obrazovku, pokud se nepřihlásíte. Pokud se pokusíte přejít na jinou obrazovku, budete přesměrováni na přihlašovací obrazovku. Pokud se přihlásíte, můžete si prohlížet další obrazovky.

Prozatím se můžete přihlásit zadáním svého uživatelského jména a hesla na přihlašovací obrazovce. Samotná autentizace uživatele je implementována jako dočasné místo. V tomto případě je hlavní důraz kladen na implementaci autentizace pomocí souborů cookie, takže podstata procesu zjišťování, jako je například to, zda je heslo správné, není podstatou.

Tento tip popisuje pouze část programu. Chcete-li získat úplný kód, stáhněte si kompletní program. Zabývá se také architekturami MVC i Razor Pages.

Vytvoření projektu

Spusťte Visual Studio a vytvořte nový projekt.

V případě Razor Pages vyberte ASP.NET Core Web App nebo pro MVC vyberte ASP.NET Core Web App (Model-View-Controller).

Zadejte název projektu podle svého výběru a umístění projektu.

Jako typ ověřování vyberte možnost Žádné. Pokud zvolíte jiné ověřování, použijete ASP.NET Core Identity. Až budete s nastavením hotovi, klikněte na tlačítko "Vytvořit".

Po vytvoření projektu se při provádění ladění zobrazí níže uvedená obrazovka. Na základě této obrazovky vytvoříme program.

Upravit program.cs (Razor Pages, MVC Common)

Přidejte definice vyžadované pro ověřování souborů cookie do programu .cs. Obory názvů, které se mají přidat, jsou následující:

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

Tady je builder.Services kód, který se má přidat do .

// === 省略 ===

// 「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 Ověřování pomocí souborů cookie můžete povolit spuštěním metody and. Pokud nepotřebujete změnit název schématu, CookieAuthenticationDefaults.AuthenticationScheme zadejte .

AddAuthorization Pokud určíte options.FallbackPolicy RequireAuthenticatedUser pro metodu Zásady vyžadované ověřením můžete použít pro všechny stránky, všechny kontrolery a akce. Pokud chcete vyžadovat autentizaci pro cokoli jiného než přihlašovací obrazovku, je to užitečná metoda, pokud jde o zmenšení kódu a prevenci chyb v popisu. Budete muset napsat kód, který nevyžaduje ověření pro přihlašovací obrazovku samostatně.

Následuje app kód pro .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Vzhledem k tomu, že chceme do aplikace přidat funkci ověřování, app.UseAuthentication() přidáme . Popis umístění je podle dokumentace MSDN, app. UseAuthorization(). Jinak je to stále šablona.

Programy pro projekty Razor Pages

Vytvoření přihlašovací stránky (Pages/Account/Login.cshtml.cs)

Vytvoření souboru

Vytvořte přihlašovací stránku. Cesta k souboru by měla být vytvořena jako "/Pages/Account/Login.cshtml". Je to proto, že výchozí přihlašovací cesta je taková. Pokud chcete tuto cestu změnit, Program.cs můžete tak učinit nastavením argumentu AddCookie metody .

Můžete jej vytvořit zkopírováním jiných souborů místo vytvoření z nabídky, ale v takovém případě prosím opravte program správně.

Povolit uživatelům přístup na přihlašovací stránku bez přihlášení

Program.cs Vzhledem k tomu, že ke všem stránkám lze přistupovat pouze tehdy, když jste přihlášeni, musíte nastavit pouze přihlašovací stránku, abyste k ní měli přístup, i když nejste přihlášeni.

AllowAnonymous Přidáním atributů lze k cílové stránce přistupovat, i když není ověřena. AllowAnonymous Atributy mohou být použity i na jiných místech než na přihlašovací obrazovce, například v operacích rozhraní API, které nesouvisejí s ověřováním souborů 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
  {
  }
}

Vytvoření proměnné pro příjem vstupu

Když se přihlásíte, deklarujete své uživatelské jméno, abyste mohli tyto hodnoty přijímat, protože zadáte heslo.

// 省略

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

Definujte uživatelské jméno a heslo pro ověřování přihlášení

Původně by to bylo uloženo v databázi atd., ale protože úsudek uživatelů tentokrát není hlavním zaměřením, udělám to jako dočasné místo.

// 省略

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

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

Proces přihlášení

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

Toto je proces ověřování po stisknutí tlačítka přihlášení. Pokud se uživatelské jméno a heslo shodují, je ověření možné.

Popsaný kód je minimální kód vyžadovaný pro autentizaciClaimClaimsIdentityClaimsPrincipal a HttpContext.SignInAsync Voláním metody je vygenerován a ověřen soubor cookie.

Pokud jsou vyžadovány další deklarace identity nebo je vyžadováno vypršení platnosti souboru cookie, přidají se další parametry.

Po přihlášení budete přesměrováni na program , kde /Index je vyžadováno ověření.

Proces odhlášení

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

Logout Při přístupu pomocí obslužné rutiny se zpracuje pro odhlášení. HttpContext.SignOutAsync Voláním metody můžete cookie smazat a vrátit ji do stavu, kdy nejste přihlášeni.

Vytvoření pohledu

Vzhled nebereme v úvahu. Přidejte pole pro zadání uživatelského jména a hesla, jak je znázorněno níže, a umístěte tlačítko pro přihlášení. Měli byste mít také odkaz pro přístup bez přihlášení k testování /Index .

Vzhledem k tomu, že zadání uživatelského jména a hesla je problematické, nastaví se počáteční hodnota.

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

Vytvoření odkazu pro odhlášení (/Pages/Shared/_Layout.cshtml)

Na domovské obrazovce nebudeme provádět žádné změny, ale do navigační lišty umístíme odkaz pro odhlášení. Pro testování také zveřejněte odkaz, který vás přenese na přihlašovací obrazovku bez odhlášení.

<!-- 中略 -->
<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 vše pro kód Razor Pages.

Programy pro projekty MVC

Vytvoření modelu přihlášení

Vytvořili jste model pro příjem hodnot zadaných na přihlašovací obrazovce.

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

Vytvoření AccountController

Vytvořte kontrolery a akce potřebné k vytvoření přihlašovací obrazovky. Vytvořte název AccountController kontroleru jako . Je to proto, že ve výchozím nastavení jsou název ovladače a název akce na přihlašovací obrazovce nastaveny na "~/Account/Login". Pokud chcete tuto cestu změnit, můžete tak učinit v možnostech AddCookie metody v Program.cs. Prozatím budeme pokračovat s výchozím nastavením.

Nejprve vytvoříme stranu kontroleru.

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 Udělením atributu lze všechny akce v něm provádět bez ověření. To vám umožní přístup pouze na přihlašovací obrazovku bez ověření.

AllowAnonymous Atributy mohou být také použity v kontrolerech pouze pro rozhraní API, které nesouvisejí s ověřováním souborů cookie na jiných místech než na přihlašovací obrazovce.

Dále definujte uživatele a hesla, která se mohou přihlásit. Původně by to bylo uloženo v databázi atd., ale protože úsudek uživatelů tentokrát není hlavním zaměřením, udělám to jako dočasné místo.

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

Následuje akce, která zobrazí přihlašovací obrazovku. Vzhledem k tomu, že je pouze zobrazen, vrátí zobrazení tak, jak je.

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

Níže je uveden kód, který má být zpracován při přihlášení.

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

Toto je proces ověřování po stisknutí tlačítka přihlášení. Pokud se uživatelské jméno a heslo shodují, je ověření možné.

Popsaný kód je minimální kód vyžadovaný pro autentizaciClaimClaimsIdentityClaimsPrincipal a HttpContext.SignInAsync Voláním metody je vygenerován a ověřen soubor cookie.

Pokud jsou vyžadovány další deklarace identity nebo je vyžadováno vypršení platnosti souboru cookie, přidají se další parametry.

Po přihlášení budete přesměrováni na program , kde ~/Home/Index je vyžadováno ověření.

Nakonec je přidán proces odhlášení.

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

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

HttpContext.SignOutAsync Voláním metody můžete cookie smazat a vrátit ji do stavu, kdy nejste přihlášeni.

Vytvoření zobrazení (přihlašovací formulář) (/Views/Account/Login.cshtml)

Login Kliknutím pravým tlačítkem myši na akci přidejte zobrazení. Můžete jej také vytvořit zkopírováním z jiného souboru.

Vzhled nebereme v úvahu. Přidejte pole pro zadání uživatelského jména a hesla, jak je znázorněno níže, a umístěte tlačítko pro přihlášení. Měli byste mít také odkaz pro přístup bez přihlášení k testování Home/Index .

Vzhledem k tomu, že zadání uživatelského jména a hesla je problematické, nastaví se počáteční hodnota.

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

Vytvoření odkazu pro odhlášení (/Views/Shared/_Layout.cshtml)

Na domovské obrazovce nebudeme provádět žádné změny, ale do navigační lišty umístíme odkaz pro odhlášení. Pro testování také zveřejněte odkaz, který vás přenese na přihlašovací obrazovku bez odhlášení.

<!-- 中略 -->
<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 pro kód MVC vše.

Potvrzení o provozu

Tím je dokončena minimální požadovaná implementace ověřování souborů cookie. Zkuste jej spustit a uvidíte, jak to funguje. Chování by se mělo měnit v závislosti na tom, zda jste přihlášeni nebo ne. Jako jednoduchý příklad můžete vidět následující chování.

operace
Výsledek operace
Přejít domů bez přihlášení Přesměrovat na přihlašovací obrazovku
přihlášení do systému Přechod na domovskou obrazovku
Odhlaste se z domova a jděte domů bez přihlášení Přesměrovat na přihlašovací obrazovku
Jděte domů bez odhlášení z domova a přihlášení Přechod na domovskou obrazovku