Sukurkite prisijungimo mechanizmą naudodami slapukų autentifikavimą ir sukurkite mechanizmą, kuris bus nukreiptas, jei nesate autentifikuotas
Darbo aplinka
- Vizualinė studija
-
- "Visual Studio" bendruomenė 2022 m
- ASP.NET Core (MVC, Razor puslapiai)
- 6.0
Iš pradžių
Šį kartą "ASP.NET Core" naudos slapukų autentifikavimą kaip prisijungimo autentifikavimo mechanizmą. Galite manyti, kad slapukų autentifikavimas yra panašus į tradicinių formų autentifikavimą.
Kitas "ASP.NET Core" autentifikavimo mechanizmas yra "ASP.NET Core Identity". Be autentifikavimo naudojant formas, tai leidžia autentifikuoti naudojant API, naudotis išorinėmis prisijungimo paslaugomis, tvarkyti ir iš naujo nustatyti slaptažodžius ir kt. Galite naudoti daug funkcijų. Tačiau šį kartą tiesiog sukūrus paprastą prisijungimo ekraną, tai bus šiek tiek perdėtas autentifikavimo mechanizmas. Šį kartą jo nenaudosime.
Šį kartą pateiktuose slapukų autentifikavimo patarimuose negalite rodyti nieko kito, išskyrus prisijungimo ekraną, nebent prisijungiate. Jei bandysite pereiti į kitą ekraną, būsite nukreipti į prisijungimo ekraną. Jei prisijungiate, galite peržiūrėti kitus ekranus.
Kol kas galite prisijungti prisijungimo ekrane įvesdami savo vartotojo vardą ir slaptažodį. Pats vartotojo autentifikavimas įgyvendinamas kaip laikina vieta. Šiuo atveju pagrindinis dėmesys skiriamas slapukų autentifikavimo įgyvendinimui, todėl nustatymo proceso esmė, pavyzdžiui, ar slaptažodis yra teisingas, nėra esmė.
Šis patarimas apibūdina tik dalį programos. Norėdami gauti visą kodą, atsisiųskite visą programą. Jis taip pat apima tiek MVC, tiek "Razor Pages" sistemas.
Projekto kūrimas
Paleiskite "Visual Studio" ir sukurkite naują projektą.
"Razor Pages" pasirinkite ASP.NET "Core Web App", o MVC – ASP.NET "Core Web App" (modelis-rodinys-valdiklis).
Nurodykite pasirinktą projekto pavadinimą ir projekto vietą.
Norėdami nustatyti autentifikavimo tipą, pasirinkite "Nėra". Jei pasirinksite kitą autentifikavimą, naudosite ASP.NET Core Identity". Kai baigsite nustatymus, spustelėkite mygtuką "Sukurti".
Sukūrus projektą, toliau parodytas ekranas bus rodomas, kai bus vykdomas derinimas. Pagal šį ekraną sukursime programą.
Redaguoti programą.cs ("Razor" puslapiai, "MVC Common")
Pridėkite apibrėžimus, reikalingus slapukų autentifikavimui, į Programą .cs. Įtraukiamos šios vardų sritys:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
builder.Services
Štai kodas, kurį reikia įtraukti į .
// === 省略 ===
// 「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
Slapukų autentifikavimą galite įjungti vykdydami ir metodą.
Jei jums nereikia keisti schemos pavadinimo, CookieAuthenticationDefaults.AuthenticationScheme
nurodykite .
AddAuthorization
Jei nurodote options.FallbackPolicy
RequireAuthenticatedUser
metodą
Autentifikavimui reikalingą strategiją galite taikyti visiems puslapiams, visiems valdikliams ir veiksmams.
Jei norite reikalauti autentifikavimo niekam kitam, išskyrus prisijungimo ekraną, tai yra naudingas būdas sumažinti kodą ir išvengti klaidų aprašyme.
Turėsite atskirai parašyti kodą, kuriam nereikia autentifikuoti prisijungimo ekrano.
Toliau pateikiamas app
kodas.
// === 省略 ===
app.UseRouting();
app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可
// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// === 省略 ===
Kadangi norime prie programos pridėti autentifikavimo funkciją, app.UseAuthentication()
pridėsime .
Aprašymo vieta yra pagal MSDN dokumentaciją, programą. UseAuthorization().
Išskyrus tai, tai vis tiek yra šablonas.
"Razor Pages" projektų programos
Sukurkite prisijungimo puslapį (Pages/Account/Login.cshtml.cs)
Failo kūrimas
Sukurkite prisijungimo puslapį. Failo kelias turėtų būti sukurtas kaip "/Pages/Account/Login.cshtml".
Taip yra todėl, kad numatytasis prisijungimo kelias yra toks.
Jei norite pakeisti šį kelią, Program.cs
galite tai padaryti nustatydami metodo argumentą AddCookie
.
Galite jį sukurti nukopijuodami kitus failus, o ne kurdami jį iš meniu, tačiau tokiu atveju pataisykite programą teisingai.
Leiskite vartotojams pasiekti prisijungimo puslapį neprisijungus
Program.cs
Kadangi visus puslapius galima pasiekti tik prisijungus, turite nustatyti tik prisijungimo puslapį, kad galėtumėte jį pasiekti, net jei nesate prisijungę.
AllowAnonymous
Pridėjus atributų, tikslinį puslapį galima pasiekti, net jei jis nėra autentifikuotas.
AllowAnonymous
Atributai gali būti naudojami kitose vietose nei prisijungimo ekranas, pvz., API operacijose, nesusijusiose su slapukų autentifikavimu.
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
{
}
}
Sukurkite kintamąjį, kad gautumėte įvestį
Kai prisijungiate, deklaruojate savo vartotojo vardą, kad galėtumėte gauti šias reikšmes, nes įvedate slaptažodį.
// 省略
[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; } = "";
}
Apibrėžkite prisijungimo autentifikavimo vartotojo vardą ir slaptažodį
Iš pradžių jis būtų saugomas duomenų bazėje ir pan., Bet kadangi šį kartą vartotojo sprendimas nėra pagrindinis dėmesys, aš padarysiu jį kaip laikiną vietą.
// 省略
[AllowAnonymous]
public class LoginModel : PageModel
{
// 省略
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Prisijungimo procesas
<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");
}
Tai yra autentifikavimo procesas paspaudus prisijungimo mygtuką. Jei vartotojo vardas ir slaptažodis sutampa, autentifikuoti galima.
Aprašytas kodas yra minimalus kodas, reikalingas autentifikavimui,Claim
ClaimsIdentity
ClaimsPrincipal
ir
HttpContext.SignInAsync
Iškviečiant šį metodą, sugeneruojamas ir autentifikuojamas slapukas.
Jei reikia papildomų pretenzijų arba reikia pasibaigti slapukų galiojimo laikui, pridedami papildomi parametrai.
Prisijungę būsite nukreipti į , kur /Index
reikalingas autentifikavimas.
Atsijungimo procesas
<summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
Logout
Kai pasiekiama naudojant tvarkytoją, jis apdorojamas, kad atsijungtų.
HttpContext.SignOutAsync
Paskambinę šiuo metodu, galite ištrinti slapuką ir grąžinti jį į būseną, kurioje nesate prisijungę.
Rodinio kūrimas
Mes neatsižvelgiame į išvaizdą. Pridėkite laukus, kad įvestumėte savo vartotojo vardą ir slaptažodį, kaip parodyta toliau, ir įdėkite mygtuką, kad prisijungtumėte.
Taip pat turėtumėte turėti nuorodą, kad galėtumėte pasiekti neprisijungę, kad galėtumėte išbandyti /Index
.
Kadangi sunku įvesti vartotojo vardą ir slaptažodį, nustatoma pradinė vertė.
@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"); }
}
Atsijungimo nuorodos kūrimas (/Pages/Shared/_Layout.cshtml)
Neatliksime jokių pagrindinio ekrano pakeitimų, bet naršymo juostoje įdėsime atsijungimo nuorodą. Be to, norėdami išbandyti, paskelbkite nuorodą, nukreipiančią į prisijungimo ekraną neatsijungdami.
<!-- 中略 -->
<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>
<!-- 中略 -->
Viskas dėl "Razor Pages" kodo.
MVC projektų programos
Prisijungimo modelio kūrimas
Sukūrėte modelį, kad gautumėte prisijungimo ekrane įvestas reikšmes.
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" kūrimas
Sukurkite valdiklius ir veiksmus, reikalingus prisijungimo ekranui sukurti.
Sukurkite valdiklio pavadinimą AccountController
kaip .
Taip yra todėl, kad pagal numatytuosius nustatymus valdiklio vardas ir veiksmo pavadinimas prisijungimo ekrane yra nustatyti į "~/Account/Login".
Jei norite pakeisti šį kelią, galite tai padaryti metodo parinktyse AddCookie
, esančiose Programa.cs.
Kol kas tęsime numatytuosius nustatymus.
Pirmiausia sukurkime valdiklio pusę.
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
Suteikus atributą, visi jame esantys veiksmai gali būti atliekami be autentifikavimo.
Tai leidžia pasiekti tik prisijungimo ekraną be autentifikavimo.
AllowAnonymous
Atributai taip pat gali būti naudojami tik API valdikliuose, nesusijusiuose su slapukų autentifikavimu kitose vietose, išskyrus prisijungimo ekraną.
Tada apibrėžkite vartotojus ir slaptažodžius, kurie gali prisijungti. Iš pradžių jis būtų saugomas duomenų bazėje ir pan., Bet kadangi šį kartą vartotojo sprendimas nėra pagrindinis dėmesys, aš padarysiu jį kaip laikiną vietą.
[AllowAnonymous]
public class AccountController : Controller
{
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Toliau pateikiamas veiksmas, rodantis prisijungimo ekraną. Kadangi jis tik rodomas, jis grąžina vaizdą tokį, koks yra.
<summary>ログイン画面を表示します。</summary>
public IActionResult Login() => View();
Žemiau pateikiamas kodas, kurį reikia apdoroti prisijungiant.
<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");
}
Tai yra autentifikavimo procesas paspaudus prisijungimo mygtuką. Jei vartotojo vardas ir slaptažodis sutampa, autentifikuoti galima.
Aprašytas kodas yra minimalus kodas, reikalingas autentifikavimui,Claim
ClaimsIdentity
ClaimsPrincipal
ir
HttpContext.SignInAsync
Iškviečiant šį metodą, sugeneruojamas ir autentifikuojamas slapukas.
Jei reikia papildomų pretenzijų arba reikia pasibaigti slapukų galiojimo laikui, pridedami papildomi parametrai.
Prisijungę būsite nukreipti į , kur ~/Home/Index
reikalingas autentifikavimas.
Galiausiai pridedamas atsijungimo procesas.
<summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// ログイン画面にリダイレクト
return RedirectToAction(nameof(Login));
}
HttpContext.SignOutAsync
Paskambinę šiuo metodu, galite ištrinti slapuką ir grąžinti jį į būseną, kurioje nesate prisijungę.
Sukurti rodinį (prisijungimo forma) (/Views/Account/Login.cshtml)
Login
Dešiniuoju pelės mygtuku spustelėkite veiksmą, kad įtrauktumėte rodinį. Taip pat galite jį sukurti nukopijuodami iš kito failo.
Mes neatsižvelgiame į išvaizdą. Pridėkite laukus, kad įvestumėte savo vartotojo vardą ir slaptažodį, kaip parodyta toliau, ir įdėkite mygtuką, kad prisijungtumėte.
Taip pat turėtumėte turėti nuorodą, kad galėtumėte pasiekti neprisijungę, kad galėtumėte išbandyti Home/Index
.
Kadangi sunku įvesti vartotojo vardą ir slaptažodį, nustatoma pradinė vertė.
@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"); }
}
Atsijungimo saito kūrimas (/Views/Shared/_Layout.cshtml)
Neatliksime jokių pagrindinio ekrano pakeitimų, bet naršymo juostoje įdėsime atsijungimo nuorodą. Be to, norėdami išbandyti, paskelbkite nuorodą, nukreipiančią į prisijungimo ekraną neatsijungdami.
<!-- 中略 -->
<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>
<!-- 中略 -->
Viskas MVC kodui.
Operacijos patvirtinimas
Tai užbaigia minimalų būtiną slapukų autentifikavimo įgyvendinimą. Pabandykite jį paleisti ir pažiūrėkite, kaip jis veikia. Elgesys turėtų keistis priklausomai nuo to, ar esate prisijungę, ar ne. Kaip paprastą pavyzdį galite matyti tokį elgesį.
Operacijos | ⇒ | rezultatas |
---|---|---|
Grįžkite namo neprisijungę | ⇒ | Peradresuoti į prisijungimo ekraną |
Prisijungti | ⇒ | Eikite į pagrindinį ekraną |
Atsijunkite nuo namų ir eikite namo neprisijungę | ⇒ | Peradresuoti į prisijungimo ekraną |
Eikite namo neatsijungę nuo namų ir neprisijungę | ⇒ | Eikite į pagrindinį ekraną |