Tạo nhiều màn hình đăng nhập và giới hạn các trang có thể được truy cập bởi màn hình bạn đã đăng nhập

Trang Cập Nhật :
Ngày tạo trang :

Môi trường hoạt động

Visual Studio
  • Cộng đồng Visual Studio 2022
ASP.NET Core (MVC, Razor Pages)
6.0

Lúc đầu

Phần này mô tả cách chuẩn bị nhiều màn hình đăng nhập trong một ứng dụng và tách các trang có thể được truy cập bởi mỗi màn hình đăng nhập. Phương pháp xây dựng một màn hình đăng nhập duy nhất được giải thích trong "Tạo cơ chế đăng nhập bằng xác thực cookie và tạo cơ chế chuyển hướng nếu bạn không được xác thực", và nội dung này được giải thích dựa trên giả định rằng bạn có kiến thức về việc xây dựng một màn hình đăng nhập duy nhất. Do đó, quá trình giống như một màn hình đăng nhập duy nhất chỉ là một lời giải thích đơn giản.

Tạo dự án

Tôi đang tạo một mẫu Razor Pages và MVC, nhưng bạn chỉ có thể tạo dự án bạn muốn sử dụng.

Chỉnh sửa chương trình.cs (Razor Pages, MVC Common)

Lần này, chúng tôi sẽ sử dụng phương pháp tách các trang có thể được truy cập bởi trang đăng nhập bằng tên "lược đồ".

Đầu tiên, thêm không gian tên vào đầu mã.

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

Sau đây là một trình xây dựng. Mã để thêm vào Dịch vụ.

// === 省略 ===

// 「Razor Pages」のコード
// builder.Services.AddRazorPages();
// 「MVC」のコード
// builder.Services.AddControllersWithViews();

// ※ここから追加

// Cookie による認証スキームを追加する
builder.Services
  .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie("FirstAuth", option =>
  {
    option.LoginPath = "/Account/LoginFirst";
  })
  .AddCookie("SecondAuth", option =>
  {
    option.LoginPath = "/Account/LoginSecond";
  });

builder.Services.AddAuthorization(options =>
{
  // 認証属性を設定していない画面は FirstAuth スキーマの認証が必要となる
  options.FallbackPolicy = new AuthorizationPolicyBuilder("FirstAuth")
    .RequireAuthenticatedUser()
    .Build();
});

// ※ここまで追加

var app = builder.Build();

// === 省略 ===

Sự khác biệt so với lần trước là cookie được thêm vào hai. AddCookie Đối số đầu tiên của mỗi chứa tên lược đồ xác định thông tin đăng nhập. Tên này có thể là bất cứ thứ gì miễn là nó là một tên khác. Đối số thứ hai là URL trang đăng nhập sẽ được chuyển hướng khi đăng nhập được truy cập mà không cần đăng nhập. Nhân tiện, nếu bạn không chỉ định tên lược đồ, nó CookieAuthenticationDefaults.AuthenticationScheme sẽ giống như .

FallbackPolicy Nó cũng chỉ định lược đồ làm cài đặt cho FirstAuth . Do đó, cần có quyền truy cập vào FirstAuth xác thực sơ đồ hoặc không bị Index.cshtml ảnh hưởng nàyPrivacy.cshtml.

Mã cho ứng dụng sau giống như đối với một lần đăng nhập.

// === 省略 ===

app.UseRouting();

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

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

// === 省略 ===

Các chương trình dành cho dự án Razor Pages

Tạo trang sau khi đăng nhập

Tạo hai trang sau khi đăng nhập. Vì nó là một trang chỉ hiển thị, nên không sao nếu bạn tạo nó để bạn có thể xem nơi bạn đã đăng nhập.

Trang/IndexFirst.cshtml

@page
@model IndexFirstModel
@{
  ViewData["Title"] = "First page";
}

<div class="text-center">
    <h1 class="display-4">First Page</h1>
</div>

Không có gì đặc biệt quan trọng về nó, nhưng hãy đảm bảo rằng mô hình bạn đang tham chiếu khớp với IndexFirstModel trang bạn đã tạo, chẳng hạn như .

Trang/IndexFirst.cshtml.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace CookieAuthenticationMultipleRazorPages.Pages
{
  [Authorize(AuthenticationSchemes = "FirstAuth")]
  public class IndexFirstModel : PageModel
  {
    private readonly ILogger<IndexFirstModel> _logger;

    public IndexFirstModel(ILogger<IndexFirstModel> logger)
    {
      _logger = logger;
    }

    public void OnGet() { }
  }
}

Không có xử lý đặc biệt vì nó chỉ được hiển thị, nhưng lưu ý rằng chúng tôi đã thêm làm thuộc tính của Authorize tên lớp. AuthenticationSchemes Đối số được đặt thành tên lược đồ được chỉ định trong Chương trình.cs. Điều này đảm bảo rằng bạn chỉ có thể xem trang này nếu bạn đăng nhập bằng tên lược đồ này. Nếu bạn truy cập trang này mà không đăng nhập, bạn sẽ được chuyển hướng đến trang đăng nhập.

Trang/IndexSecond.cshtml

Đây là trang thứ hai sau khi đăng nhập.

@page
@model IndexSecondModel
@{
  ViewData["Title"] = "Second page";
}

<div class="text-center">
  <h1 class="display-4">Second Page</h1>
</div>

Trang/IndexSecond.cshtml.cs

Lưu ý rằng mã về cơ bản giống như trang đăng nhập đầu tiên, nhưng tên lược đồ thì khác.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace CookieAuthenticationMultipleRazorPages.Pages
{
  [Authorize(AuthenticationSchemes = "SecondAuth")]
  public class IndexSecondModel : PageModel
  {
    private readonly ILogger<IndexSecondModel> _logger;

    public IndexSecondModel(ILogger<IndexSecondModel> logger)
    {
      _logger = logger;
    }

    public void OnGet() { }
  }
}

Tạo trang đăng nhập

Tạo hai trang đăng nhập.

Trang/Tài khoản/LoginFirst.cshtml.cs

Nối thêm thuộc tính để bạn có thể truy cập thuộc tính đó mà không cần AllowAnonymous đăng nhập.

using Microsoft.AspNetCore.Authentication;
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 CookieAuthenticationMultipleRazorPages.Pages.Account
{
  [AllowAnonymous]
  public class LoginFirstModel : PageModel
  {
  }
}

Tạo một biến và một tài khoản người dùng giả để nhận thông tin đăng nhập bạn đã nhập.

[AllowAnonymous]
public class LoginFirstModel : PageModel
{
  /// <summary>ユーザー名。</summary>
  [BindProperty]
  [Required]
  [DisplayName("ユーザー名")]
  public string UserName { get; set; } = "";

  /// <summary>パスワード。</summary>
  [BindProperty]
  [Required]
  [DataType(DataType.Password)]
  [DisplayName("パスワード")]
  public string Password { get; set; } = "";

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

Sau đây là quá trình đăng nhập.

/// <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, "FirstAuth");
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync("FirstAuth", principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToPage("/IndexFirst");
}

Sự khác biệt so với một lần đăng nhập là mỗi tên lược đồ được chỉ định. Vị trí bạn chỉ định là ClaimsIdentity đối số của và đối số của HttpContext.SignInAsync . Tại đây bạn có thể chỉ định lược đồ nào bạn muốn đăng nhập.

Logout cũng ở dạng chỉ định tên lược đồ.

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

Trang/Tài khoản/LoginFirst.cshtml

Mặt xem không khác gì một lần đăng nhập. Vui lòng khớp với tên model cần tham khảo.

@page
@model LoginFirstModel
@{}

<p>Login1</p>

<form method="post">
  <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="/IndexFirst">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{
    await Html.RenderPartialAsync("_ValidationScriptsPartial");
  }
}

Trang/Tài khoản/LoginSecond.cshtml.cs

Đây là một logic đăng nhập khác. First Second Nó chỉ khác nhau.

using Microsoft.AspNetCore.Authentication;
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 CookieAuthenticationMultipleRazorPages.Pages.Account
{
  [AllowAnonymous]
  public class LoginSecondModel : PageModel
  {
    /// <summary>ユーザー名。</summary>
    [BindProperty]
    [Required]
    [DisplayName("ユーザー名")]
    public string UserName { get; set; } = "";

    /// <summary>パスワード。</summary>
    [BindProperty]
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("パスワード")]
    public string Password { get; set; } = "";

    /// <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, "SecondAuth");
      var principal = new ClaimsPrincipal(identity);

      // 認証クッキーをレスポンスに追加
      await HttpContext.SignInAsync("SecondAuth", principal);

      // ログインが必要な画面にリダイレクトします
      return RedirectToPage("/IndexSecond");
    }

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

Trang/Tài khoản/LoginSecond.cshtml

Cảnh. First Nó chỉ có vậy và Second khác nhau.

@page
@model LoginSecondModel
@{}

<p>Login Second</p>

<form method="post">
  <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="/IndexSecond">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{
    await Html.RenderPartialAsync("_ValidationScriptsPartial");
  }
}

Trang/Chia sẻ/_Layout.cshtml

Thêm liên kết đăng xuất cho mỗi liên kết.

<!-- 中略 -->
<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/LoginFirst" asp-page-handler="Logout">ログアウト(First)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/LoginFirst">ログアウトせずログインへ(First)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/LoginSecond" asp-page-handler="Logout">ログアウト(Second)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/LoginSecond">ログアウトせずログインへ(Second)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/IndexFirst">IndexFirst</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/IndexSecond">IndexSecond</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

Các chương trình cho các dự án MVC

Tạo mô hình đăng nhập

Lần này, các giá trị đầu vào của hai màn hình đăng nhập giống nhau, vì vậy chúng tôi sẽ chia sẻ chúng và chỉ tạo một.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

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

Tạo AccountController

Hai quá trình đăng nhập được AccountController bao gồm trong , vì vậy bạn chỉ cần thêm một bộ điều khiển.

AllowAnonymous Thuộc tính nó để bạn có thể truy cập nó mà không cần đăng nhập.

using CookieAuthenticationMultipleMvc.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace CookieAuthenticationMultipleMvc.Controllers
{
  /// <remarks>
  /// <see cref="AllowAnonymous"/> 属性は Cookie 認証していなくてもアクセスできる Action (Controller) であることを示す。
  /// </remarks>
  [AllowAnonymous]
  public class AccountController : Controller
  {
  }
}

Tạo một tài khoản người dùng giả.

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

Thêm hành động để hiển thị trang cho lần đăng nhập đầu tiên.

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

Dưới đây là mã sẽ được xử lý khi đăng nhập.

/// <summary>ログイン処理を実行します。</summary>
[HttpPost]
public async Task<IActionResult> LoginFirst(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, "FirstAuth");
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync("FirstAuth", principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToAction(nameof(HomeController.Index), "HomeFirst");
}

Sự khác biệt so với một lần đăng nhập là mỗi tên lược đồ được chỉ định. Vị trí bạn chỉ định là ClaimsIdentity đối số của và đối số của HttpContext.SignInAsync . Tại đây bạn có thể chỉ định lược đồ nào bạn muốn đăng nhập.

Logout cũng ở dạng chỉ định tên lược đồ.

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

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

Tôi cũng sẽ thêm lần đăng nhập thứ hai. First Không có sự khác biệt nào khác chỉ bằng cách thay đổi phần của Second .

// 中略

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

/// <summary>ログイン処理を実行します。</summary>
[HttpPost]
public async Task<IActionResult> LoginSecond(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, "SecondAuth");
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync("SecondAuth", principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToAction(nameof(HomeController.Index), "HomeSecond");
}

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

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

// 中略

Tạo dạng xem (biểu mẫu đăng nhập)

Tạo hai dạng xem mỗi dạng xem.

Không có nhiều sự khác biệt giữa một lần đăng nhập và một mã, vì vậy tôi sẽ đăng mã như hiện tại.

Lượt xem/Tài khoản/LoginFirst.cshtml

@model LoginModel
@{}

<h1>Login First</h1>

<form asp-action="LoginFirst">
  <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="HomeFirst" asp-action="Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Lượt xem/Tài khoản/LoginSecond.cshtml

@model LoginModel
@{}

<h1>Login Second</h1>

<form asp-action="LoginSecond">
  <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="HomeSecond" asp-action="Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Tạo màn hình sau khi đăng nhập

HomeController Tạo hai bộ điều khiển mới mà không cần sử dụng bộ điều khiển hiện có. Đây là những bộ điều khiển mà bạn có thể truy cập sau khi đăng nhập. Mỗi màn hình được đặt để có thể truy cập khác nhau tùy thuộc vào màn hình bạn đăng nhập.

HomeFirstController.cs

Vì nó chỉ hiển thị màn hình, không có gì để thêm xử lý.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace CookieAuthenticationMultipleMvc.Controllers
{
  [Authorize(AuthenticationSchemes = "FirstAuth")]
  public class HomeFirstController : Controller
  {
    public IActionResult Index() => View();
  }
}

Thay vào đó, nó gắn một thuộc tính vào controller và AuthenticationSchemes chỉ định tên lược đồ làm Authorize đối số. FirstAuth Điều này đảm bảo rằng bạn chỉ có thể truy cập bộ điều khiển này nếu bạn đang xác thực bằng lược đồ.

HomeSecondController.cs

Second Tạo mặt theo cách tương tự.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace CookieAuthenticationMultipleMvc.Controllers
{
  [Authorize(AuthenticationSchemes = "SecondAuth")]
  public class HomeSecondController : Controller
  {
    public IActionResult Index() => View();
  }
}

Lượt xem/HomeFirst/Index.cshtml

Không có gì đặc biệt khó khăn vì nó chỉ được hiển thị. Phân biệt chúng để bạn có thể xem đó là trang nào.

@{
  ViewData["Title"] = "First View";
}

<div class="text-center">
  <h1 class="display-4">First View</h1>
</div>

Lượt xem/HomeSecond/Index.cshtml

Chỉ cần hiển thị nó ở đây là tốt.

@{
  ViewData["Title"] = "Second View";
}

<div class="text-center">
  <h1 class="display-4">Second View</h1>
</div>

Lượt xem/Chia sẻ/_Layout.cshtml

Thêm liên kết đăng xuất cho mỗi liên kết.

<!-- 中略 -->
<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-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="LogoutFirst">ログアウト(First)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="LoginFirst">ログアウトせずログインへ(First)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="LogoutSecond">ログアウト(Second)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="LoginSecond">ログアウトせずログインへ(Second)</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="HomeFirst" asp-action="Index">IndexFirst</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="HomeSecond" asp-action="Index">IndexSecond</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

Xác nhận hoạt động

Vui lòng chạy nó để xem nó hoạt động như thế nào. Tôi chắc chắn rằng bạn đã thấy hoạt động đăng nhập một lần, vì vậy Tôi nghĩ rằng đó là một ý tưởng tốt để kiểm tra những gì sẽ xảy ra khi bạn truy cập vào mỗi màn hình khi bạn giữ trạng thái đăng nhập trong mẫu sau.

  • Cả Thứ nhất và Thứ hai đều không được đăng nhập
  • Đầu tiên là đăng nhập và thứ hai là không đăng nhập
  • Đầu tiên là không đăng nhập, Thứ hai là đăng nhập
  • Cả Thứ nhất và Thứ hai đều được đăng nhập