Създайте механизъм за вход с помощта на удостоверяване с "бисквитки" и създайте механизъм, който да бъде пренасочен, ако не сте удостоверени

Страницата се актуализира :
Дата на създаване на страница :

Работна среда

Визуално студио
  • Общност на Visual Studio 2022
ASP.NET Ядро (MVC, Razor Pages)
6.0

Отначало

Този път ASP.NET Core ще използва удостоверяването на "бисквитките" като механизъм за удостоверяване при влизане. Можете да мислите за удостоверяването на "бисквитките" като подобно на традиционното удостоверяване на формуляри.

Друг механизъм за удостоверяване ASP.NET Core е ASP.NET Core Identity. В допълнение към удостоверяването с помощта на формуляри, това ви позволява да се удостоверявате с API, да използвате външни услуги за вход, да управлявате и нулирате пароли и т.н. Можете да използвате много функции. Въпреки това, от гледна точка на просто създаване на прост екран за вход този път, това ще бъде малко преувеличен механизъм за удостоверяване. Този път няма да го използваме.

В съветите за удостоверяване на бисквитките, въведени този път, не можете да показвате нищо друго освен екрана за вход, освен ако не влезете. Ако се опитате да навигирате до друг екран, ще бъдете пренасочени към екрана за вход. Ако влезете, можете да видите други екрани.

За момента можете да влезете, като въведете потребителското си име и парола на екрана за вход. Самото удостоверяване на потребителя се изпълнява като временно място. В този случай основният фокус е върху прилагането на удостоверяване на "бисквитките", така че същността на процеса на определяне, като например дали паролата е правилна, не е същността.

Този съвет описва само част от програмата. За пълния код изтеглете пълната програма. Той също така обхваща както MVC, така и Razor Pages frameworks.

Създаване на проект

Стартирайте Visual Studio и създайте нов проект.

За Razor Pages изберете ASP.NET Core Web App или за MVC изберете ASP.NET Core Web App (Model-View-Controller).

Задайте име на проект по ваш избор и местоположение за проекта.

За типа удостоверяване изберете "Няма". Ако изберете друго удостоверяване, ще използвате ASP.NET Core Identity. Когато приключите с настройките, кликнете върху бутона "Създаване".

След създаването на проекта, екранът, показан по-долу, ще се покаже при изпълнение на отстраняване на грешки. Ще създадем програма, базирана на този екран.

Редактиране на програма.cs (Razor Pages, MVC Common)

Добавете дефинициите, необходими за удостоверяване на бисквитките, към Program.cs. Пространствата от имена, които трябва да се добавят, са следните:

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

builder.Services Ето кода, който да добавите към .

// === 省略 ===

// 「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 Можете да активирате удостоверяването на бисквитките, като изпълните метода and. Ако не е необходимо да променяте името на схемата, CookieAuthenticationDefaults.AuthenticationScheme задайте .

AddAuthorization Ако зададете options.FallbackPolicy RequireAuthenticatedUser за метода Можете да приложите правила, необходими за удостоверяване, към всички страници, всички контролери и действия. Ако искате да изисквате удостоверяване за нещо различно от екрана за вход, това е полезен метод по отношение на намаляване на кода и предотвратяване на грешки в описанието. Ще трябва да напишете код, който не изисква удостоверяване за екрана за вход отделно.

По-долу е app кодът за .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Тъй като искаме да добавим функционалност за удостоверяване към приложението, app.UseAuthentication() ще добавим . Местоположението на описанието е съгласно документацията на MSDN, ап. UseAuthorization(). Освен това, това все още е шаблон.

Програми за проекти на Razor Pages

Създаване на страница за вход (Страници/Акаунт/Вход.cshtml.cs)

Създаване на файл

Създайте страница за вход. Пътят на файла трябва да бъде създаден като "/Pages/Account/Login.cshtml". Това е така, защото пътят за влизане по подразбиране е такъв. Ако искате да промените този път, можете Program.cs да го направите, като зададете аргумента на метода на AddCookie .

Можете да го създадете, като копирате други файлове, вместо да го създавате от менюто, но в този случай, моля, поправете програмата правилно.

Позволяване на потребителите да имат достъп до страницата за вход, без да влизат

Program.cs Тъй като всички страници могат да бъдат достъпни само когато сте влезли в системата, трябва да зададете само страницата за вход, така че да имате достъп до нея, дори ако не сте влезли в нея.

AllowAnonymous Чрез добавяне на атрибути, целевата страница може да бъде достъпна, дори ако не е удостоверена. AllowAnonymous Атрибутите могат да се използват на други места, различни от екрана за вход, като API операции, които не са свързани с удостоверяването на "бисквитките".

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

Създаване на променлива за получаване на входни данни

Когато влезете, декларирате потребителското си име, за да можете да получавате тези стойности, защото въвеждате паролата си.

// 省略

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

Дефиниране на потребителско име и парола за удостоверяване при влизане

Първоначално щеше да се съхранява в база данни и т.н., но тъй като преценката на потребителя този път не е основният фокус, ще го направя като временно място.

// 省略

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

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

Процес на влизане

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

Това е процесът на удостоверяване след натискане на бутона за вход. Ако потребителското име и паролата съвпадат, е възможно удостоверяване.

Описаният код е минималният код, необходим за удостоверяване,ClaimClaimsIdentityClaimsPrincipal и HttpContext.SignInAsync Чрез извикване на метода се генерира и удостоверява бисквитка.

Ако са необходими допълнителни претенции или е необходимо изтичане на срока на бисквитката, се добавят допълнителни параметри.

След като влезете, ще бъдете пренасочени към , където /Index се изисква удостоверяване.

Процес на излизане

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

Logout Когато се осъществи достъп с манипулатор, той се обработва, за да излезе. HttpContext.SignOutAsync Извиквайки метода, можете да изтриете бисквитката и да я върнете в състояние, в което не сте влезли.

Създаване на изглед

Не се съобразяваме с външния вид. Добавете полета за въвеждане на вашето потребителско име и парола, както е показано по-долу, и поставете бутон, за да влезете. Също така трябва да имате връзка за /Index достъп, без да влизате за тестване.

Тъй като е трудно да въведете потребителското име и паролата, първоначалната стойност е зададена.

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

Създаване на връзка за излизане (/Pages/Shared/_Layout.cshtml)

Няма да правим никакви промени в началния екран, но ще поставим връзка за излизане в навигационната лента. Също така, за тестване, публикувайте връзка, която ви отвежда до екрана за вход, без да излизате.

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

Това е всичко за кода на Razor Pages.

Програми за MVC проекти

Създаване на модел за вход

Създали сте модел за получаване на стойностите, въведени на екрана за вход.

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

Създаване на акаунт контролер

Създайте контролерите и действията, необходими за създаване на екрана за вход. Създайте името AccountController на контролера като . Това е така, защото по подразбиране името на контролера и името на действието на екрана за вход са зададени на "~/Account/Login". Ако искате да промените този път, можете да го направите в опциите на AddCookie метода в Програма.cs. Засега ще продължим с настройките по подразбиране.

Първо, нека създадем страната на контролера.

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 Чрез предоставяне на атрибута всички действия в него могат да бъдат извършени, без да бъдат удостоверени. Това ви позволява да получите достъп само до екрана за вход без удостоверяване.

AllowAnonymous Атрибутите могат да се използват и в контролери само за API, които не са свързани с удостоверяването на "бисквитките" на други места, различни от екрана за вход.

След това определете потребителите и паролите, които могат да влязат. Първоначално щеше да се съхранява в база данни и т.н., но тъй като преценката на потребителя този път не е основният фокус, ще го направя като временно място.

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

Следното е действие, което показва екрана за влизане. Тъй като се показва само, той връща изгледа такъв, какъвто е.

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

По-долу е кодът, който трябва да бъде обработен при влизане.

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

Това е процесът на удостоверяване след натискане на бутона за вход. Ако потребителското име и паролата съвпадат, е възможно удостоверяване.

Описаният код е минималният код, необходим за удостоверяване,ClaimClaimsIdentityClaimsPrincipal и HttpContext.SignInAsync Чрез извикване на метода се генерира и удостоверява бисквитка.

Ако са необходими допълнителни претенции или е необходимо изтичане на срока на бисквитката, се добавят допълнителни параметри.

След като влезете, ще бъдете пренасочени към , където ~/Home/Index се изисква удостоверяване.

Накрая се добавя процесът на излизане.

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

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

HttpContext.SignOutAsync Извиквайки метода, можете да изтриете бисквитката и да я върнете в състояние, в което не сте влезли.

Създаване на изглед (формуляр за вход) (/Views/Account/Login.cshtml)

Login Щракнете с десния бутон върху действието, за да добавите изглед. Можете също да го създадете, като го копирате от друг файл.

Не се съобразяваме с външния вид. Добавете полета за въвеждане на вашето потребителско име и парола, както е показано по-долу, и поставете бутон, за да влезете. Също така трябва да имате връзка за Home/Index достъп, без да влизате за тестване.

Тъй като е трудно да въведете потребителското име и паролата, първоначалната стойност е зададена.

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

Създаване на връзка за излизане (/Views/Shared/_Layout.cshtml)

Няма да правим никакви промени в началния екран, но ще поставим връзка за излизане в навигационната лента. Също така, за тестване, публикувайте връзка, която ви отвежда до екрана за вход, без да излизате.

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

Това е за кода на MVC.

Потвърждаване на операцията

Това завършва минимално необходимото внедряване на удостоверяване на бисквитките. Опитайте да го стартирате и да видите как работи. Поведението трябва да се промени в зависимост от това дали сте влезли или не. Като прост пример можете да видите следното поведение.

операция
Резултат от операция
Приберете се вкъщи, без да влизате в системата Пренасочване към екрана за вход
Вход Отидете на началния екран
Излезте от дома си и се приберете вкъщи, без да влизате в профила си Пренасочване към екрана за вход
Приберете се вкъщи, без да излизате от дома и да влизате в профила си Отидете на началния екран