Hozzon létre egy bejelentkezési mechanizmust cookie-hitelesítéssel, és hozzon létre egy mechanizmust, amely átirányítja, ha nincs hitelesítve
Működési környezet
- Visual Studio
-
- Visual Studio Community 2022
- ASP.NET Core (MVC, Razor Pages)
- 6.0
Először
Ezúttal a ASP.NET Core cookie-hitelesítést használ bejelentkezési hitelesítési mechanizmusként. A cookie-hitelesítés hasonló a hagyományos űrlapos hitelesítéshez.
A ASP.NET Core másik hitelesítési mechanizmusa a ASP.NET Core Identity. Az űrlapokkal történő hitelesítés mellett ez lehetővé teszi az API-kkal való hitelesítést, külső bejelentkezési szolgáltatások használatát, jelszavak kezelését és visszaállítását stb. Sok funkciót használhat. Azonban abból a szempontból, hogy ezúttal csak egy egyszerű bejelentkezési képernyőt hoz létre, ez egy kissé túlzott hitelesítési mechanizmus lesz. Ezúttal nem fogjuk használni.
Az ezúttal bemutatott cookie-hitelesítési tippekben a bejelentkezési képernyőn kívül csak akkor jeleníthet meg mást, ha bejelentkezik. Ha megpróbál navigálni egy másik képernyőre, a rendszer átirányítja a bejelentkezési képernyőre. Ha bejelentkezik, megtekintheti a többi képernyőt.
Egyelőre úgy jelentkezhet be, hogy megadja felhasználónevét és jelszavát a bejelentkezési képernyőn. Maga a felhasználói hitelesítés ideiglenes helyként van megvalósítva. Ebben az esetben a fő hangsúly a cookie-hitelesítés megvalósításán van, így a meghatározási folyamat lényege, például a jelszó helyessége nem a lényeg.
Ez a tipp a programnak csak egy részét ismerteti. A teljes kódhoz töltse le a teljes programot. Ez magában foglalja mind az MVC, mind a Razor Pages keretrendszereket.
Projekt létrehozása
Indítsa Visual Studio, és hozzon létre egy új projektet.
A Razor Pages esetében válassza a ASP.NET Core Web App lehetőséget, vagy az MVC esetében válassza a ASP.NET Core Web App (Model-View-Controller) lehetőséget.
Adja meg a választott projektnevet és a projekt helyét.
A hitelesítés típusaként válassza a "Nincs" lehetőséget. Ha más hitelesítést választ, ASP.NET alapvető identitást fogja használni. Ha végzett a beállításokkal, kattintson a "Létrehozás" gombra.
A projekt létrehozása után az alábbi képernyő jelenik meg a hibakeresés végrehajtásakor. Létrehozunk egy programot ezen a képernyőn alapul.
Program szerkesztése.cs (Razor Pages, MVC Common)
Adja hozzá a cookie-hitelesítéshez szükséges definíciókat a Program.cs mezőhöz. A hozzáadandó névterek a következők:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
Itt látható builder.Services
a kód, amelyet hozzá kell adni 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();
// === 省略 ===
AddAuthentication
AddCookie
A cookie-hitelesítést a és metódus végrehajtásával engedélyezheti.
Ha nem kell módosítania a séma nevét, CookieAuthenticationDefaults.AuthenticationScheme
adja meg a értéket.
AddAuthorization
options.FallbackPolicy
RequireAuthenticatedUser
Ha megadja a metódust
A hitelesítéshez szükséges házirendet minden lapra, vezérlőre és műveletre alkalmazhatja.
Ha a bejelentkezési képernyőn kívül bármi máshoz szeretne hitelesítést kérni, ez hasznos módszer a kód csökkentése és a leírás hibáinak megelőzése szempontjából.
Külön kell írnia olyan kódot, amely nem igényel hitelesítést a bejelentkezési képernyőhöz.
A kódja a következő app
: .
// === 省略 ===
app.UseRouting();
app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可
// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// === 省略 ===
Mivel hitelesítési funkciót szeretnénk hozzáadni az alkalmazáshoz, app.UseAuthentication()
hozzáadjuk .
A leírás helye az MSDN dokumentációjának és alkalmazásának megfelelően található. UseAuthorization().
Ettől eltekintve ez még mindig sablon.
Programok Razor Pages projektekhez
Hozzon létre egy bejelentkezési oldalt (Pages/Account/Login.cshtml.cs)
Fájl létrehozása
Hozzon létre egy bejelentkezési oldalt. A fájl elérési útját a következőképpen kell létrehozni: "/Pages/Account/Login.cshtml".
Ez azért van, mert az alapértelmezett bejelentkezési útvonal ilyen.
Ha módosítani szeretné ezt az elérési utat, Program.cs
ezt a AddCookie
metódus argumentumának beállításával teheti meg.
Létrehozhatja más fájlok másolásával ahelyett, hogy a menüből hozná létre, de ebben az esetben kérjük, javítsa ki helyesen a programot.
A bejelentkezési oldal elérésének engedélyezése a felhasználók számára bejelentkezés nélkül
Program.cs
Mivel minden oldal csak akkor érhető el, ha be van jelentkezve, csak a bejelentkezési oldalt kell beállítania, hogy akkor is elérhesse, ha nincs bejelentkezve.
AllowAnonymous
Attribútumok hozzáadásával a céloldal akkor is elérhető, ha nincs hitelesítve.
AllowAnonymous
Az attribútumok a bejelentkezési képernyőn kívül más helyeken is használhatók, például a cookie-hitelesítéshez nem kapcsolódó API-műveletekben.
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
{
}
}
Változó létrehozása bemenet fogadásához
Amikor bejelentkezik, megadja felhasználónevét, hogy megkaphatja ezeket az értékeket, mert megadja jelszavát.
// 省略
[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; } = "";
}
Felhasználónév és jelszó megadása a bejelentkezési hitelesítéshez
Eredetileg adatbázisban stb. tárolták volna, de mivel ezúttal nem a felhasználói megítélés a fő hangsúly, ideiglenes helyként fogom használni.
// 省略
[AllowAnonymous]
public class LoginModel : PageModel
{
// 省略
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Bejelentkezési folyamat
<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");
}
Ez a hitelesítési folyamat a bejelentkezési gomb megnyomása után. Ha a felhasználónév és a jelszó megegyezik, a hitelesítés lehetséges.
A leírt kód a hitelesítéshez minimálisan szükséges kód,Claim
ClaimsIdentity
ClaimsPrincipal
és
HttpContext.SignInAsync
A metódus meghívásával cookie jön létre és hitelesítődik.
Ha további jogcímekre van szükség, vagy a cookie lejáratára van szükség, további paraméterek kerülnek hozzáadásra.
A bejelentkezés után a rendszer átirányítja a oldalra, ahol /Index
hitelesítésre van szükség.
Kijelentkezési folyamat
<summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
Logout
Ha kezelővel fér hozzá, a rendszer feldolgozza a kijelentkezéshez.
HttpContext.SignOutAsync
A metódus meghívásával törölheti a cookie-t, és visszaállíthatja olyan állapotba, ahol nincs bejelentkezve.
Nézet létrehozása
Nem vesszük figyelembe a megjelenést. Adjon hozzá mezőket a felhasználónév és jelszó megadásához az alábbiak szerint, és helyezzen el egy gombot a bejelentkezéshez.
Rendelkeznie kell egy linkkel is, amellyel tesztelés nélkül /Index
is hozzáférhet.
Mivel a felhasználónév és a jelszó megadása nehézkes, a kezdeti érték be van állítva.
@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"); }
}
Kijelentkezési hivatkozás létrehozása (/Pages/Shared/_Layout.cshtml)
A kezdőképernyőn nem hajtunk végre módosításokat, de a navigációs sávon elhelyezünk egy kijelentkezési hivatkozást. Ezenkívül teszteléshez tegyen közzé egy linket, amely kijelentkezés nélkül a bejelentkezési képernyőre viszi.
<!-- 中略 -->
<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>
<!-- 中略 -->
Ennyit a Razor Pages kódról.
MVC projektek programjai
Bejelentkezési modell létrehozása
Létrehozott egy modellt a bejelentkezési képernyőn megadott értékek fogadásához.
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 létrehozása
Hozza létre a bejelentkezési képernyő létrehozásához szükséges vezérlőket és műveleteket.
Hozza létre a vezérlő nevét AccountController
.
Ez azért van, mert alapértelmezés szerint a vezérlő neve és a művelet neve a bejelentkezési képernyőn "~/Account/Login" értékre van állítva.
Ha módosítani szeretné ezt az elérési utat, ezt megteheti a Program.cs metódus beállításaiban AddCookie
.
Egyelőre folytatjuk az alapértelmezett beállításokat.
Először hozzuk létre a vezérlő oldalt.
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
Az attribútum megadásával az összes benne lévő művelet hitelesítés nélkül végrehajtható.
Ez lehetővé teszi, hogy hitelesítés nélkül csak a bejelentkezési képernyőt érje el.
AllowAnonymous
Az attribútumok olyan csak API-vezérlőkben is használhatók, amelyek nem kapcsolódnak a cookie-hitelesítéshez a bejelentkezési képernyőn kívül.
Ezután határozza meg a bejelentkezéshez szükséges felhasználókat és jelszavakat. Eredetileg adatbázisban stb. tárolták volna, de mivel ezúttal nem a felhasználói megítélés a fő hangsúly, ideiglenes helyként fogom használni.
[AllowAnonymous]
public class AccountController : Controller
{
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
A következő művelet megjeleníti a bejelentkezési képernyőt. Mivel csak megjelenik, a nézetet változatlanul adja vissza.
<summary>ログイン画面を表示します。</summary>
public IActionResult Login() => View();
Az alábbiakban látható a bejelentkezéskor feldolgozandó kód.
<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");
}
Ez a hitelesítési folyamat a bejelentkezési gomb megnyomása után. Ha a felhasználónév és a jelszó megegyezik, a hitelesítés lehetséges.
A leírt kód a hitelesítéshez minimálisan szükséges kód,Claim
ClaimsIdentity
ClaimsPrincipal
és
HttpContext.SignInAsync
A metódus meghívásával cookie jön létre és hitelesítődik.
Ha további jogcímekre van szükség, vagy a cookie lejáratára van szükség, további paraméterek kerülnek hozzáadásra.
A bejelentkezés után a rendszer átirányítja a oldalra, ahol ~/Home/Index
hitelesítésre van szükség.
Végül hozzáadódik a kijelentkezési folyamat.
<summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// ログイン画面にリダイレクト
return RedirectToAction(nameof(Login));
}
HttpContext.SignOutAsync
A metódus meghívásával törölheti a cookie-t, és visszaállíthatja olyan állapotba, ahol nincs bejelentkezve.
Nézet létrehozása (bejelentkezési űrlap) (/Views/Account/Login.cshtml)
Login
Kattintson a jobb gombbal a műveletre nézet hozzáadásához. Létrehozhatja egy másik fájlból történő másolással is.
Nem vesszük figyelembe a megjelenést. Adjon hozzá mezőket a felhasználónév és jelszó megadásához az alábbiak szerint, és helyezzen el egy gombot a bejelentkezéshez.
Rendelkeznie kell egy linkkel is, amellyel tesztelés nélkül Home/Index
is hozzáférhet.
Mivel a felhasználónév és a jelszó megadása nehézkes, a kezdeti érték be van állítva.
@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"); }
}
Kijelentkezési hivatkozás létrehozása (/Views/Shared/_Layout.cshtml)
A kezdőképernyőn nem hajtunk végre módosításokat, de a navigációs sávon elhelyezünk egy kijelentkezési hivatkozást. Ezenkívül teszteléshez tegyen közzé egy linket, amely kijelentkezés nélkül a bejelentkezési képernyőre viszi.
<!-- 中略 -->
<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>
<!-- 中略 -->
Ennyi az MVC kódhoz.
A működés megerősítése
Ezzel befejeződik a cookie-hitelesítés minimálisan szükséges megvalósítása. Próbálja meg futtatni, és nézze meg, hogyan működik. A viselkedésnek attól függően kell változnia, hogy be van-e jelentkezve vagy sem. Egyszerű példaként a következő viselkedést láthatja.
Művelet | ⇒ | művelet eredménye |
---|---|---|
Menj haza bejelentkezés nélkül | ⇒ | Átirányítás a bejelentkezési képernyőre |
bejelentkezés | ⇒ | Ugrás a kezdőképernyőre |
Jelentkezzen ki otthonról, és menjen haza bejelentkezés nélkül | ⇒ | Átirányítás a bejelentkezési képernyőre |
Menjen haza anélkül, hogy kijelentkezne otthonából és bejelentkezne | ⇒ | Ugrás a kezdőképernyőre |