여러 로그인 화면을 만들고 로그인한 화면에서 액세스할 수 있는 페이지를 제한합니다.
운영 환경
- 비주얼 스튜디오
-
- Visual Studio 커뮤니티 2022
- ASP.NET Core(MVC, Razor 페이지)
- 6.0
처음에
이 섹션에서는 하나의 응용 프로그램에서 여러 로그인 화면을 준비하고 각 로그인 화면에서 액세스할 수 있는 페이지를 분리하는 방법에 대해 설명합니다. 단일 로그인 화면을 구축하는 방법은 "쿠키 인증을 사용하여 로그인 메커니즘 만들기 및 인증되지 않은 경우 리디렉션되는 메커니즘 만들기"에 설명되어 있으며, 이 내용은 단일 로그인 화면 구축에 대한 지식이 있는 것을 전제로 설명합니다. 따라서 단일 로그인 화면과 동일한 프로세스는 간단한 설명일 뿐입니다.
프로젝트 만들기
Razor Pages 및 MVC 샘플을 만들고 있지만 사용하려는 프로젝트만 만들어도 괜찮습니다.
Program>편집:.cs(Razor Pages, MVC Common)
이번에는 로그인 페이지에서 액세스 할 수있는 페이지를 "스키마"라는 이름으로 구분하는 방법을 사용합니다.
먼저 코드 맨 위에 네임스페이스를 추가합니다.
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
다음은 빌더입니다. 서비스에 추가할 코드입니다.
// === 省略 ===
// 「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();
// === 省略 ===
지난번과 다른 점은 쿠키가 2개로 추가된다는 것입니다.
AddCookie
각각의 첫 번째 인수에는 로그인을 식별하는 스키마 이름이 포함됩니다. 이 이름은 다른 이름이면 무엇이든 될 수 있습니다.
두 번째 인수는 로그인하지 않고 로그인에 액세스할 때 리디렉션되는 로그인 페이지 URL입니다.
그건 그렇고, CookieAuthenticationDefaults.AuthenticationScheme
스키마 이름을 지정하지 않으면 와 동일합니다.
FallbackPolicy
또한 스키마를 에 대한 FirstAuth
설정으로 지정합니다. 따라서 이 손대 Index.cshtml
지 않은 인증 또는 Privacy.cshtml
스키마 인증에 대한 FirstAuth
액세스가 필요합니다.
다음 앱의 코드는 단일 로그인의 경우와 동일합니다.
// === 省略 ===
app.UseRouting();
app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可
// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// === 省略 ===
Razor Pages 프로젝트용 프로그램
로그인 후 페이지 만들기
로그인 후 두 개의 페이지를 만듭니다. 표시 만 되는 페이지이기 때문에, 로그인한 위치를 볼 수 있도록 만들면 OK입니다.
Pages/IndexFirst.cshtml (영문)
@page
@model IndexFirstModel
@{
ViewData["Title"] = "First page";
}
<div class="text-center">
<h1 class="display-4">First Page</h1>
</div>
특별히 중요한 것은 없지만 참조하는 모델이 만든 페이지와 일치 IndexFirstModel
하는지 확인하십시오.
Pages/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() { }
}
}
표시 만 있기 때문에 특별한 처리는 없지만 클래스 이름의 속성 Authorize
으로 추가했습니다.
AuthenticationSchemes
인수는 Program.cs 에 지정된 스키마 이름으로 설정됩니다.
이렇게 하면 이 스키마 이름으로 로그인하는 경우에만 이 페이지를 볼 수 있습니다. 로그인하지 않고 이 페이지를 방문하면 로그인 페이지로 리디렉션됩니다.
Pages/IndexSecond.cshtml (영문)
로그인 후 두 번째 페이지입니다.
@page
@model IndexSecondModel
@{
ViewData["Title"] = "Second page";
}
<div class="text-center">
<h1 class="display-4">Second Page</h1>
</div>
Pages/IndexSecond.cshtml.cs
코드는 기본적으로 첫 번째 로그인 페이지와 동일하지만 스키마 이름이 다릅니다.
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() { }
}
}
로그인 페이지 만들기
두 개의 로그인 페이지를 만듭니다.
Pages/Account/LoginFirst.cshtml.cs
로그인하지 않고 AllowAnonymous
액세스할 수 있도록 속성을 추가합니다.
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
{
}
}
변수와 더미 사용자 계정을 만들어 입력한 로그인 정보를 수신합니다.
[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" },
};
}
다음은 로그인 프로세스입니다.
<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");
}
단일 로그인과의 차이점은 각 스키마 이름이 지정된다는 것입니다.
지정하는 위치는 의 인수와 의 HttpContext.SignInAsync
인수입니다ClaimsIdentity
. 여기에서 로그인할 스키마를 지정할 수 있습니다.
로그아웃은 스키마 이름을 지정하는 형식이기도 합니다.
<summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync("FirstAuth");
}
Pages/Account/LoginFirst.cshtml입니다.
보기 측은 단일 로그인과 다르지 않습니다. 참조할 모델명과 일치하십시오.
@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");
}
}
Pages/Account/LoginSecond.cshtml.cs
다음은 또 다른 로그인 로직입니다. First
Second
다만 다를 뿐이다.
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");
}
}
}
페이지/계정/LoginSecond.cshtml
보기. First
그것은 단지 그것과 Second
다릅니다.
@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");
}
}
페이지/공유/_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/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>
<!-- 中略 -->
MVC 프로젝트용 프로그램
로그인 모델 만들기
이번에는 두 로그인 화면의 입력 값이 같기 때문에 공유하여 하나만 만듭니다.
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; } = "";
}
}
AccountController 만들기
두 개의 로그인 프로세스가 AccountController
에 포함되어 있으므로 하나의 컨트롤러만 추가하면 됩니다.
AllowAnonymous
로그인하지 않고 액세스할 수 있도록 속성을 지정합니다.
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
{
}
}
더미 사용자 계정을 만듭니다.
[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 LoginFirst() => View();
아래는 로그인 시 처리해야 하는 코드입니다.
<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");
}
단일 로그인과의 차이점은 각 스키마 이름이 지정된다는 것입니다.
지정하는 위치는 의 인수와 의 HttpContext.SignInAsync
인수입니다ClaimsIdentity
. 여기에서 로그인할 스키마를 지정할 수 있습니다.
로그아웃은 스키마 이름을 지정하는 형식이기도 합니다.
<summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> LogoutFirst()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync("FirstAuth");
// ログイン画面にリダイレクト
return RedirectToAction(nameof(LoginFirst));
}
두 번째 로그인도 추가하겠습니다. First
의 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));
}
// 中略
보기 만들기(로그인 양식)
각각 두 개의 보기를 만듭니다.
한 번의 로그인과 코드의 차이는 크지 않기 때문에 코드를 그대로 게시합니다.
Views/Account/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"); }
}
보기/계정/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"); }
}
로그인 후 화면 생성
HomeController
기존 컨트롤러를 사용하지 않고 두 개의 새 컨트롤러를 만듭니다.
로그인 후 액세스할 수 있는 컨트롤러입니다.
각 화면은 로그인한 화면에 따라 다르게 액세스할 수 있도록 설정되어 있습니다.
HomeFirstController.cs
화면만 표시하기 때문에 처리를 추가할 필요가 없습니다.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace CookieAuthenticationMultipleMvc.Controllers
{
[Authorize(AuthenticationSchemes = "FirstAuth")]
public class HomeFirstController : Controller
{
public IActionResult Index() => View();
}
}
대신 컨트롤러 AuthenticationSchemes
에 특성을 연결하고 스키마 이름을 인수로 Authorize
지정합니다.
FirstAuth
이렇게 하면 스키마로 인증하는 경우에만 이 컨트롤러에 액세스할 수 있습니다.
HomeSecondController.cs
Second
같은 방법으로 면을 만듭니다.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace CookieAuthenticationMultipleMvc.Controllers
{
[Authorize(AuthenticationSchemes = "SecondAuth")]
public class HomeSecondController : Controller
{
public IActionResult Index() => View();
}
}
보기/HomeFirst/Index.cshtml
표시되는 것만으로도 특히 어려운 것은 없습니다. 어떤 페이지인지 알 수 있도록 구분하십시오.
@{
ViewData["Title"] = "First View";
}
<div class="text-center">
<h1 class="display-4">First View</h1>
</div>
Views/HomeSecond/Index.cshtml (뷰/HomeSecond/Index.cshtml)
여기에도 보여주세요.
@{
ViewData["Title"] = "Second View";
}
<div class="text-center">
<h1 class="display-4">Second View</h1>
</div>
보기/공유/_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-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>
<!-- 中略 -->
작동 확인
어떻게 작동하는지 보려면 실행하십시오. 이미 단일 로그인 작업을 본 적이 있기 때문에 로그인 상태를 다음과 같은 패턴으로 유지했을 때 각 화면에 액세스하면 어떻게 되는지 확인하는 것이 좋다고 생각합니다.
- 첫 번째와 두 번째 모두 로그인되지 않았습니다.
- 첫 번째는 로그인되고 두 번째는 로그인되지 않습니다.
- 첫 번째는 로그인되지 않았고 두 번째는 로그인되어 있습니다.
- 첫 번째와 두 번째 모두 로그인되어 있습니다.