Cree un mecanismo de inicio de sesión mediante la autenticación de cookies y cree un mecanismo para ser redirigido si no está autenticado

Actualización de la página :
Fecha de creación de la página :

Entorno operativo

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

Al principio

Esta vez, ASP.NET Core utilizará la autenticación de cookies como mecanismo de autenticación de inicio de sesión. Puede pensar en la autenticación de cookies como algo similar a la autenticación de formularios tradicionales.

Otro mecanismo de autenticación para ASP.NET Core es ASP.NET Core Identity. Además de la autenticación mediante formularios, esto le permite autenticarse con API, utilizar servicios de inicio de sesión externos, administrar y restablecer contraseñas, etc. Puede utilizar muchas funciones. Sin embargo, desde el punto de vista de la creación de una pantalla de inicio de sesión simple esta vez, será un mecanismo de autenticación algo exagerado. No lo usaremos esta vez.

En los consejos de autenticación de cookies introducidos esta vez, no puede mostrar nada más que la pantalla de inicio de sesión a menos que inicie sesión. Si intenta navegar a otra pantalla, será redirigido a la pantalla de inicio de sesión. Si inicia sesión, puede ver otras pantallas.

Por el momento, puede iniciar sesión ingresando su nombre de usuario y contraseña en la pantalla de inicio de sesión. La autenticación de usuario en sí se implementa como un lugar temporal. En este caso, el enfoque principal está en la implementación de la autenticación de cookies, por lo que la esencia del proceso de determinación, como si la contraseña es correcta, no es la esencia.

Este consejo describe solo una parte del programa. Para obtener el código completo, descargue el programa completo. También cubre los marcos MVC y Razor Pages.

Crear un proyecto

Inicie Visual Studio y cree un nuevo proyecto.

Para Razor Pages, seleccione ASP.NET aplicación web principal o, para MVC, seleccione ASP.NET aplicación web principal (modelo-vista-controlador).

Especifique un nombre de proyecto de su elección y una ubicación para el proyecto.

Para el tipo de autenticación, seleccione "Ninguno". Si elige otra autenticación, utilizará ASP.NET identidad principal. Cuando haya terminado con la configuración, haga clic en el botón "Crear".

Después de crear el proyecto, se mostrará la pantalla que se muestra a continuación cuando se ejecute la depuración. Crearemos un programa basado en esta pantalla.

Editar programa.cs (Razor Pages, MVC Common)

Agregue las definiciones necesarias para la autenticación de cookies a Program.cs. Los espacios de nombres que se van a agregar son los siguientes:

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

Este es builder.Services el código que se debe agregar a .

// === 省略 ===

// 「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 Puede habilitar la autenticación de cookies ejecutando el método and. Si no necesita cambiar el nombre del esquema, CookieAuthenticationDefaults.AuthenticationScheme especifique .

AddAuthorization Si especifica options.FallbackPolicy RequireAuthenticatedUser para el método Puede aplicar una directiva de autenticación necesaria a todas las páginas, todos los controladores y acciones. Si desea requerir autenticación para cualquier otra cosa que no sea la pantalla de inicio de sesión, es un método útil en términos de reducir el código y evitar errores en la descripción. Tendrá que escribir código que no requiera autenticación para la pantalla de inicio de sesión por separado.

A continuación se muestra app el código de .

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Dado que queremos agregar la funcionalidad de autenticación a la aplicación, app.UseAuthentication() agregaremos . La ubicación de la descripción se realiza de acuerdo con la documentación de MSDN, la aplicación. UseAuthorization(). Aparte de eso, sigue siendo una plantilla.

Programas para proyectos de Razor Pages

Crear una página de inicio de sesión (Pages/Account/Login.cshtml.cs)

Crear un archivo

Crea una página de inicio de sesión. La ruta de acceso del archivo debe crearse como "/Pages/Account/Login.cshtml". Esto se debe a que la ruta de inicio de sesión predeterminada es así. Si desea cambiar esta ruta, Program.cs puede hacerlo estableciendo el argumento del AddCookie método de .

Puede crearlo copiando otros archivos en lugar de crearlo desde el menú, pero en ese caso, corrija el programa correctamente.

Permitir que los usuarios accedan a la página de inicio de sesión sin iniciar sesión

Program.cs Dado que solo se puede acceder a todas las páginas cuando ha iniciado sesión, debe configurar solo la página de inicio de sesión para que pueda acceder a ella incluso si no ha iniciado sesión.

AllowAnonymous Al agregar atributos, se puede acceder a la página de destino incluso si no está autenticada. AllowAnonymous Los atributos se pueden utilizar en otros lugares que no sean la pantalla de inicio de sesión, como operaciones de API no relacionadas con la autenticación de cookies.

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

Crear una variable para recibir la entrada

Cuando inicias sesión, declaras tu nombre de usuario para poder recibir esos valores porque ingresas tu contraseña.

// 省略

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

Definir un nombre de usuario y una contraseña para la autenticación de inicio de sesión

Originalmente, se almacenaría en una base de datos, etc., pero dado que el juicio del usuario no es el enfoque principal esta vez, lo haré como un lugar temporal.

// 省略

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

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

Proceso de inicio de sesión

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

Este es el proceso de autenticación después de presionar el botón de inicio de sesión. Si el nombre de usuario y la contraseña coinciden, la autenticación es posible.

El código descrito es el código mínimo requerido para la autenticación,ClaimClaimsIdentityClaimsPrincipal y HttpContext.SignInAsync Al llamar al método, se genera una cookie y se autentica.

Si se requieren notificaciones adicionales o se requiere la caducidad de las cookies, se agregan parámetros adicionales.

Después de iniciar sesión, se le redirige a , donde /Index se requiere autenticación.

Proceso de cierre de sesión

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

Logout Cuando se accede con un controlador, se procesa para cerrar la sesión. HttpContext.SignOutAsync Al llamar al método, puede eliminar la cookie y devolverla a un estado en el que no haya iniciado sesión.

Creación de una vista

No tenemos en cuenta la apariencia. Agregue campos para ingresar su nombre de usuario y contraseña como se muestra a continuación, y coloque un botón para iniciar sesión. También debe tener un enlace para acceder sin iniciar sesión para /Index realizar la prueba.

Dado que es problemático ingresar el nombre de usuario y la contraseña, se establece el valor inicial.

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

Crear un vínculo de cierre de sesión (/Pages/Shared/_Layout.cshtml)

No haremos ningún cambio en la pantalla de inicio, pero pondremos un enlace de cierre de sesión en la barra de navegación. Además, para realizar pruebas, publique un enlace que lo lleve a la pantalla de inicio de sesión sin cerrar sesión.

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

Eso es todo para el código de Razor Pages.

Programas para proyectos MVC

Creación de un modelo de inicio de sesión

Ha creado un modelo para recibir los valores introducidos en la pantalla de inicio de sesión.

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

Creación de un AccountController

Cree los controladores y las acciones necesarias para crear la pantalla de inicio de sesión. Cree el nombre AccountController del controlador como . Esto se debe a que, de forma predeterminada, el nombre del controlador y el nombre de la acción en la pantalla de inicio de sesión se establecen en "~/Account/Login". Si desea cambiar esta ruta de acceso, puede hacerlo en las opciones del AddCookie método en Program.cs. Por ahora, procederemos con la configuración predeterminada.

Primero, vamos a crear el lado del controlador.

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 Al otorgar el atributo, todas las acciones en él se pueden realizar sin autenticarse. Esto le permite acceder solo a la pantalla de inicio de sesión sin autenticación.

AllowAnonymous Los atributos también se pueden usar en controladores solo de API que no están relacionados con la autenticación de cookies en otros lugares que no sean la pantalla de inicio de sesión.

A continuación, defina los usuarios y contraseñas que pueden iniciar sesión. Originalmente, se almacenaría en una base de datos, etc., pero dado que el juicio del usuario no es el enfoque principal esta vez, lo haré como un lugar temporal.

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

La siguiente es una acción que muestra la pantalla de inicio de sesión. Dado que solo se muestra, devuelve la vista tal cual.

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

A continuación se muestra el código que se procesará al iniciar sesión.

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

Este es el proceso de autenticación después de presionar el botón de inicio de sesión. Si el nombre de usuario y la contraseña coinciden, la autenticación es posible.

El código descrito es el código mínimo requerido para la autenticación,ClaimClaimsIdentityClaimsPrincipal y HttpContext.SignInAsync Al llamar al método, se genera una cookie y se autentica.

Si se requieren notificaciones adicionales o se requiere la caducidad de las cookies, se agregan parámetros adicionales.

Después de iniciar sesión, se le redirige a , donde ~/Home/Index se requiere autenticación.

Finalmente, se agrega el proceso de cierre de sesión.

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

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

HttpContext.SignOutAsync Al llamar al método, puede eliminar la cookie y devolverla a un estado en el que no haya iniciado sesión.

Crear una vista (formulario de inicio de sesión) (/Views/Account/Login.cshtml)

Login Haga clic con el botón derecho en la acción para agregar una vista. También puede crearlo copiándolo de otro archivo.

No tenemos en cuenta la apariencia. Agregue campos para ingresar su nombre de usuario y contraseña como se muestra a continuación, y coloque un botón para iniciar sesión. También debe tener un enlace para acceder sin iniciar sesión para Home/Index realizar la prueba.

Dado que es problemático ingresar el nombre de usuario y la contraseña, se establece el valor inicial.

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

Crear un vínculo de cierre de sesión (/Views/Shared/_Layout.cshtml)

No haremos ningún cambio en la pantalla de inicio, pero pondremos un enlace de cierre de sesión en la barra de navegación. Además, para realizar pruebas, publique un enlace que lo lleve a la pantalla de inicio de sesión sin cerrar sesión.

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

Eso es todo para el código MVC.

Confirmación de funcionamiento

Esto completa la implementación mínima requerida de la autenticación de cookies. Intente ejecutarlo y vea cómo funciona. El comportamiento debería cambiar dependiendo de si ha iniciado sesión o no. Como ejemplo sencillo, puede ver el siguiente comportamiento.

la operación ⇒
Resultado deoperación
Volver a casa sin iniciar sesión Redirigir a la pantalla de inicio de sesión
Iniciar sesión Ir a la pantalla de inicio
Cerrar sesión en casa y volver a casa sin iniciar sesión Redirigir a la pantalla de inicio de sesión
Ir a casa sin cerrar sesión en la casa e iniciar sesión Ir a la pantalla de inicio