Ustvarite več zaslonov za prijavo in omejite strani, do katerih lahko dostopate na zaslonu, v katerega ste prijavljeni
Delovno okolje
- Visual Studio
-
- Skupnost Visual Studio 2022
- ASP.NET jedro (MVC, britvice)
- 6.0
Sprva
V tem razdelku je opisano, kako pripraviti več zaslonov za prijavo v eni aplikaciji in ločiti strani, do katerih lahko dostopate z vsakim prijavnim zaslonom. Način izgradnje enotnega prijavnega zaslona je razložen v "Ustvarjanje prijavnega mehanizma z uporabo avtentikacije piškotkov in ustvarjanje mehanizma za preusmeritev, če niste overjeni", ta vsebina pa je razložena ob predpostavki, da imate znanje o izdelavi enotnega prijavnega zaslona. Zato je postopek istega kot en sam prijavni zaslon le preprosta razlaga.
Ustvarjanje projekta
Ustvarjam britvice strani in vzorec MVC, vendar je v redu, če ustvarite samo projekt, ki ga želite uporabiti.
Uredi program.cs (britvice strani, MVC pogosto)
Tokrat bomo uporabili metodo ločevanja strani, do katerih lahko dostopate s strani za prijavo, z imenom "shema".
Najprej dodajte imenski prostor na vrh kode.
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
Sledi graditelj. Kodo, ki jo želite dodati v storitve.
// === 省略 ===
// 「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();
// === 省略 ===
Razlika od zadnjega je v tem, da se piškotki dodajo dvema.
AddCookie
Prvi argument vsakega vsebuje ime sheme, ki identificira prijavo. To ime je lahko karkoli, dokler je drugačno ime.
Drugi argument je URL strani za prijavo, ki bo preusmerjen, ko dostopate do prijave brez prijave.
Mimogrede, če ne določite imena sheme, bo CookieAuthenticationDefaults.AuthenticationScheme
enako kot .
FallbackPolicy
Prav tako določa shemo kot nastavitev za FirstAuth
. Zato je potreben dostop do FirstAuth
tega nedotaknjenega Index.cshtml
preverjanja pristnosti ali Privacy.cshtml
preverjanja pristnosti sheme.
Koda za naslednjo aplikacijo je enaka kot za eno prijavo.
// === 省略 ===
app.UseRouting();
app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可
// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// === 省略 ===
Programi za projekte Razor Pages
Ustvarjanje strani po prijavi
Po prijavi ustvarite dve strani. Ker gre za stran, ki se samo prikaže, je v redu, če jo naredite, da lahko vidite, kje ste prijavljeni.
Strani/IndexFirst.cshtml
@page
@model IndexFirstModel
@{
ViewData["Title"] = "First page";
}
<div class="text-center">
<h1 class="display-4">First Page</h1>
</div>
Pri tem ni nič posebej pomembnega, vendar se prepričajte, da se model, na katerega se sklicujete, ujema s stranjo, ki IndexFirstModel
ste jo ustvarili, na primer .
Strani/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() { }
}
}
Ni posebnega ravnanja, ker je samo prikazano, vendar upoštevajte, da smo dodali kot atribut Authorize
imena razreda.
AuthenticationSchemes
Argument je nastavljen na ime sheme, določeno v razdelku Program.cs.
To zagotavlja, da si lahko to stran ogledate le, če se prijavite s tem imenom sheme. Če obiščete to stran, ne da bi se prijavili, boste preusmerjeni na stran za prijavo.
Strani/IndexSecond.cshtml
To je druga stran po prijavi.
@page
@model IndexSecondModel
@{
ViewData["Title"] = "Second page";
}
<div class="text-center">
<h1 class="display-4">Second Page</h1>
</div>
Strani/IndexSecond.cshtml.cs
Upoštevajte, da je koda v bistvu enaka prvi strani za prijavo, vendar je ime sheme drugačno.
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() { }
}
}
Ustvarjanje strani za prijavo
Ustvarite dve strani za prijavo.
Strani/Račun/LoginFirst.cshtml.cs
Priložite atribut, da boste lahko dostopali do njega, ne da bi AllowAnonymous
se prijavili.
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
{
}
}
Ustvarite spremenljiv in lažni uporabniški račun, da boste prejeli vnesene podatke za prijavo.
[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" },
};
}
V nadaljevanju je postopek prijave.
<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");
}
Razlika od ene prijave je, da je določeno vsako ime sheme.
Lokacija, ki jo določite, je ClaimsIdentity
argument in argument HttpContext.SignInAsync
. Tukaj lahko določite, s katero shemo se želite prijaviti.
Odjava je tudi v obliki navedbe imena sheme.
<summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync("FirstAuth");
}
Strani/račun/prijavaFirst.cshtml
Stran pogleda se ne razlikuje od ene same prijave. Prosimo, ujemite ime modela, na katerega se sklicujete.
@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");
}
}
Strani/račun/LoginSecond.cshtml.cs
Tu je še ena logika prijave. First
Second
Čisto drugače je.
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");
}
}
}
Strani/Račun/LoginSecond.cshtml
Pogled. First
To je samo to in Second
so drugačni.
@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");
}
}
Strani/V skupni rabi/_Layout.cshtml
Dodajte povezavo za odjavo za vsakega.
<!-- 中略 -->
<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>
<!-- 中略 -->
Programi za MVC projekte
Ustvarjanje modela prijave
Tokrat so vhodne vrednosti obeh prijavnih zaslonov enake, zato jih bomo delili in ustvarili samo enega.
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; } = "";
}
}
Ustvarjanje upravljavca računa
Oba postopka prijave sta AccountController
vključena v , zato morate dodati samo en krmilnik.
AllowAnonymous
Dodelite ga tako, da lahko dostopate do njega, ne da bi se prijavili.
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
{
}
}
Ustvarite lažni uporabniški račun.
[AllowAnonymous]
public class AccountController : Controller
{
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Dodajte dejanje za prikaz strani za prvo prijavo.
<summary>ログイン画面を表示します。</summary>
public IActionResult LoginFirst() => View();
Spodaj je koda, ki jo je treba obdelati ob prijavi.
<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");
}
Razlika od ene prijave je, da je določeno vsako ime sheme.
Lokacija, ki jo določite, je ClaimsIdentity
argument in argument HttpContext.SignInAsync
. Tukaj lahko določite, s katero shemo se želite prijaviti.
Odjava je tudi v obliki navedbe imena sheme.
<summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> LogoutFirst()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync("FirstAuth");
// ログイン画面にリダイレクト
return RedirectToAction(nameof(LoginFirst));
}
Dodal bom tudi drugo prijavo. First
Druge razlike ni samo s spremembo dela 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));
}
// 中略
Ustvarjanje pogleda (obrazec za prijavo)
Vsak od njih ustvari dva pogleda.
Med eno prijavo in kodo ni velike razlike, zato bom kodo objavil takšno, kot je.
Ogledi/račun/prijavaFirst.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"); }
}
Pogledi/račun/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"); }
}
Ustvarjanje zaslona po prijavi
HomeController
Ustvarite dva nova krmilnika brez uporabe obstoječega.
To so krmilniki, do katerih lahko dostopate po prijavi.
Vsak zaslon je nastavljen tako, da je dostopen drugače, odvisno od zaslona, v katerega ste se prijavili.
HomeFirstController.cs
Ker prikazuje samo zaslon, ni ničesar, kar bi dodali obdelavo.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace CookieAuthenticationMultipleMvc.Controllers
{
[Authorize(AuthenticationSchemes = "FirstAuth")]
public class HomeFirstController : Controller
{
public IActionResult Index() => View();
}
}
Namesto tega krmilniku priloži atribut in AuthenticationSchemes
kot argument določi ime Authorize
sheme.
FirstAuth
To zagotavlja, da lahko do tega krmilnika dostopate le, če preverjate pristnost s shemo.
HomeSecondController.cs
Second
Ustvarite stran na enak način.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace CookieAuthenticationMultipleMvc.Controllers
{
[Authorize(AuthenticationSchemes = "SecondAuth")]
public class HomeSecondController : Controller
{
public IActionResult Index() => View();
}
}
Ogledi/HomeFirst/Index.cshtml
Nič ni posebej težkega, ker je pravkar prikazano. Razlikujte jih, da boste lahko videli, za katero stran gre.
@{
ViewData["Title"] = "First View";
}
<div class="text-center">
<h1 class="display-4">First View</h1>
</div>
Ogledi/HomeSecond/Index.cshtml
Samo pokažite ga tudi tukaj.
@{
ViewData["Title"] = "Second View";
}
<div class="text-center">
<h1 class="display-4">Second View</h1>
</div>
Ogledi/skupna raba/_Layout.cshtml
Dodajte povezavo za odjavo za vsakega.
<!-- 中略 -->
<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>
<!-- 中略 -->
Potrditev delovanja
Zaženite ga, da vidite, kako deluje. Prepričan sem, da ste že videli enotno prijavo, zato Mislim, da je dobro preveriti, kaj se zgodi, ko dostopate do vsakega zaslona, ko ohranite stanje prijave v naslednjem vzorcu.
- Niti prvi niti drugi nista prijavljena
- Prvi je prijavljen, drugi pa ni prijavljen
- Prvi ni prijavljen, drugi je prijavljen
- Tako prvi kot drugi sta prijavljena