Utwórz mechanizm logowania za pomocą uwierzytelniania plików cookie i stwórz mechanizm, który będzie przekierowywany, jeśli nie jesteś uwierzytelniony
Środowisko pracy
- Visual Studio
-
- Społeczność programu Visual Studio 2022
- ASP.NET Core (MVC, Razor Pages)
- 6.0
Na początku
Tym razem ASP.NET Core wykorzysta uwierzytelnianie plików cookie jako mechanizm uwierzytelniania logowania. Możesz myśleć o uwierzytelnianiu plików cookie jako o podobnym do uwierzytelniania za pomocą tradycyjnych formularzy.
Innym mechanizmem uwierzytelniania dla ASP.NET Core jest ASP.NET Core Identity. Oprócz uwierzytelniania za pomocą formularzy umożliwia to uwierzytelnianie za pomocą interfejsów API, korzystanie z zewnętrznych usług logowania, zarządzanie i resetowanie haseł itp. Możesz korzystać z wielu funkcji. Jednak z punktu widzenia stworzenia prostego ekranu logowania tym razem będzie to nieco przesadzony mechanizm uwierzytelniania. Tym razem go nie użyjemy.
W wprowadzonych tym razem wskazówkach dotyczących uwierzytelniania plików cookie nie możesz wyświetlić niczego poza ekranem logowania, chyba że się zalogujesz. Jeśli spróbujesz przejść do innego ekranu, zostaniesz przekierowany do ekranu logowania. Jeśli się zalogujesz, możesz wyświetlić inne ekrany.
Na razie możesz się zalogować, wpisując swoją nazwę użytkownika i hasło na ekranie logowania. Samo uwierzytelnianie użytkownika jest realizowane jako miejsce tymczasowe. W tym przypadku główny nacisk kładziony jest na wdrożenie uwierzytelniania plików cookie, więc istota procesu ustalania, taka jak poprawność hasła, nie jest istotą.
Ta wskazówka opisuje tylko część programu. Aby uzyskać pełny kod, pobierz kompletny program. Obejmuje również struktury MVC i Razor Pages.
Tworzenie projektu
Uruchom program Visual Studio i utwórz nowy projekt.
W przypadku Razor Pages wybierz pozycję ASP.NET Podstawowa aplikacja internetowa lub MVC wybierz pozycję ASP.NET Podstawowa aplikacja internetowa (Model-View-Controller).
Określ wybraną nazwę projektu i lokalizację projektu.
Jako typ uwierzytelniania wybierz "Brak". Jeśli wybierzesz inne uwierzytelnianie, użyjesz tożsamości ASP.NET podstawowej. Po zakończeniu ustawień kliknij przycisk "Utwórz".
Po utworzeniu projektu podczas debugowania zostanie wyświetlony poniższy ekran. Na podstawie tego ekranu stworzymy program.
Edytowanie pliku Program.cs (Razor Pages, MVC Common)
Dodaj definicje wymagane do uwierzytelniania plików cookie do pliku Program.cs. Przestrzenie nazw, które należy dodać, są następujące:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
builder.Services
Oto kod, który należy dodać do pliku .
// === 省略 ===
// 「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
Uwierzytelnianie plików cookie można włączyć, wykonując metodę and.
Jeśli nie ma potrzeby zmiany nazwy schematu, CookieAuthenticationDefaults.AuthenticationScheme
określ .
AddAuthorization
Jeśli określisz options.FallbackPolicy
RequireAuthenticatedUser
dla metody
Zasady wymagane uwierzytelniania można zastosować do wszystkich stron, wszystkich kontrolerów i akcji.
Jeśli chcesz wymagać uwierzytelnienia dla czegokolwiek innego niż ekran logowania, jest to przydatna metoda pod względem zmniejszenia kodu i zapobiegania błędom w opisie.
Będziesz musiał napisać kod, który nie wymaga uwierzytelniania dla ekranu logowania osobno.
Poniżej znajduje app
się kod pliku .
// === 省略 ===
app.UseRouting();
app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可
// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// === 省略 ===
Ponieważ chcemy dodać funkcjonalność uwierzytelniania do aplikacji, app.UseAuthentication()
dodamy .
Lokalizacja opisu jest zgodna z dokumentacją MSDN, aplikacja. UseAuthorization().
Poza tym nadal jest to szablon.
Programy dla projektów Razor Pages
Tworzenie strony logowania (Pages/Account/Login.cshtml.cs)
Tworzenie pliku
Utwórz stronę logowania. Ścieżka pliku powinna zostać utworzona jako "/Pages/Account/Login.cshtml".
Dzieje się tak, ponieważ domyślna ścieżka logowania jest taka.
Jeśli chcesz zmienić tę ścieżkę, możesz Program.cs
to zrobić, ustawiając argument AddCookie
metody .
Możesz go utworzyć, kopiując inne pliki zamiast tworzyć go z menu, ale w takim przypadku napraw program poprawnie.
Zezwalaj użytkownikom na dostęp do strony logowania bez logowania
Program.cs
Ponieważ dostęp do wszystkich stron można uzyskać tylko wtedy, gdy jesteś zalogowany, musisz ustawić tylko stronę logowania, aby mieć do niej dostęp, nawet jeśli nie jesteś zalogowany.
AllowAnonymous
Dodając atrybuty, można uzyskać dostęp do strony docelowej, nawet jeśli nie jest ona uwierzytelniona.
AllowAnonymous
Atrybuty mogą być używane w innych miejscach niż ekran logowania, takich jak operacje API niezwiązane z uwierzytelnianiem plików cookie.
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
{
}
}
Tworzenie zmiennej do odbierania danych wejściowych
Logując się, deklarujesz swoją nazwę użytkownika, aby móc otrzymywać te wartości, ponieważ wprowadzasz hasło.
// 省略
[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; } = "";
}
Zdefiniuj nazwę użytkownika i hasło do uwierzytelniania logowania
Pierwotnie miał być przechowywany w bazie danych itp., ale ponieważ tym razem nie skupia się na ocenie użytkownika, zrobię to jako miejsce tymczasowe.
// 省略
[AllowAnonymous]
public class LoginModel : PageModel
{
// 省略
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Proces logowania
<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");
}
Jest to proces uwierzytelniania po naciśnięciu przycisku logowania. Jeśli nazwa użytkownika i hasło są zgodne, uwierzytelnianie jest możliwe.
Opisany kod jest minimalnym kodem wymaganym do uwierzytelnienia,Claim
ClaimsIdentity
ClaimsPrincipal
a
HttpContext.SignInAsync
Wywołanie metody powoduje wygenerowanie i uwierzytelnienie pliku cookie.
Jeśli wymagane są dodatkowe oświadczenia lub wymagane jest wygaśnięcie pliku cookie, dodawane są dodatkowe parametry.
Po zalogowaniu zostaniesz przekierowany do , gdzie /Index
wymagane jest uwierzytelnienie.
Proces wylogowania
<summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
Logout
W przypadku uzyskiwania dostępu za pomocą programu obsługi jest on przetwarzany w celu wylogowania.
HttpContext.SignOutAsync
Wywołując metodę, możesz usunąć plik cookie i przywrócić go do stanu, w którym nie jesteś zalogowany.
Tworzenie widoku
Nie bierzemy pod uwagę wyglądu. Dodaj pola do wpisania nazwy użytkownika i hasła, jak pokazano poniżej, i umieść przycisk, aby się zalogować.
Powinieneś również mieć link do dostępu bez logowania się w celu /Index
przetestowania.
Ponieważ wprowadzanie nazwy użytkownika i hasła jest kłopotliwe, ustawiana jest wartość początkowa.
@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"); }
}
Utwórz link wylogowania (/Pages/Shared/_Layout.cshtml)
Nie wprowadzimy żadnych zmian na ekranie głównym, ale umieścimy link do wylogowania na pasku nawigacyjnym. Ponadto, w celu przetestowania, opublikuj link, który przeniesie Cię do ekranu logowania bez wylogowywania.
<!-- 中略 -->
<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>
<!-- 中略 -->
To tyle, jeśli chodzi o kod Razor Pages.
Programy dla projektów MVC
Tworzenie modelu logowania
Utworzono model, który będzie odbierał wartości wprowadzone na ekranie logowania.
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; } = "";
}
}
Tworzenie kontrolera konta
Utwórz kontrolery i akcje wymagane do utworzenia ekranu logowania.
Utwórz nazwę AccountController
kontrolera jako .
Dzieje się tak, ponieważ domyślnie nazwa kontrolera i nazwa akcji na ekranie logowania są ustawione na "~/Account/Login".
Jeśli chcesz zmienić tę ścieżkę, możesz to zrobić w opcjach AddCookie
metody w pliku Program.cs.
Na razie przejdziemy do ustawień domyślnych.
Najpierw utwórzmy stronę kontrolera.
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
Przyznając atrybut, wszystkie czynności w nim zawarte mogą być wykonywane bez uwierzytelniania.
Umożliwia to dostęp tylko do ekranu logowania bez uwierzytelniania.
AllowAnonymous
Atrybuty mogą być również używane w kontrolerach tylko API, które nie są związane z uwierzytelnianiem plików cookie w innych miejscach niż ekran logowania.
Następnie zdefiniuj użytkowników i hasła, które mogą się logować. Pierwotnie miał być przechowywany w bazie danych itp., ale ponieważ tym razem nie skupia się na ocenie użytkownika, zrobię to jako miejsce tymczasowe.
[AllowAnonymous]
public class AccountController : Controller
{
<summary>仮のユーザーデータベースとする。</summary>
private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
{
{ "user1", "password1" },
{ "user2", "password2" },
};
}
Poniżej znajduje się akcja, która wyświetla ekran logowania. Ponieważ jest tylko wyświetlany, zwraca widok w takiej postaci, w jakiej jest.
<summary>ログイン画面を表示します。</summary>
public IActionResult Login() => View();
Poniżej znajduje się kod, który należy przetworzyć podczas logowania.
<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");
}
Jest to proces uwierzytelniania po naciśnięciu przycisku logowania. Jeśli nazwa użytkownika i hasło są zgodne, uwierzytelnianie jest możliwe.
Opisany kod jest minimalnym kodem wymaganym do uwierzytelnienia,Claim
ClaimsIdentity
ClaimsPrincipal
a
HttpContext.SignInAsync
Wywołanie metody powoduje wygenerowanie i uwierzytelnienie pliku cookie.
Jeśli wymagane są dodatkowe oświadczenia lub wymagane jest wygaśnięcie pliku cookie, dodawane są dodatkowe parametry.
Po zalogowaniu zostaniesz przekierowany do , gdzie ~/Home/Index
wymagane jest uwierzytelnienie.
Na koniec dodawany jest proces wylogowania.
<summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
// 認証クッキーをレスポンスから削除
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// ログイン画面にリダイレクト
return RedirectToAction(nameof(Login));
}
HttpContext.SignOutAsync
Wywołując metodę, możesz usunąć plik cookie i przywrócić go do stanu, w którym nie jesteś zalogowany.
Tworzenie widoku (formularz logowania) (/Views/Account/Login.cshtml)
Login
Kliknij prawym przyciskiem myszy akcję, aby dodać widok. Możesz go również utworzyć, kopiując go z innego pliku.
Nie bierzemy pod uwagę wyglądu. Dodaj pola do wpisania nazwy użytkownika i hasła, jak pokazano poniżej, i umieść przycisk, aby się zalogować.
Powinieneś również mieć link do dostępu bez logowania się w celu Home/Index
przetestowania.
Ponieważ wprowadzanie nazwy użytkownika i hasła jest kłopotliwe, ustawiana jest wartość początkowa.
@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"); }
}
Utwórz link wylogowania (/Views/Shared/_Layout.cshtml)
Nie wprowadzimy żadnych zmian na ekranie głównym, ale umieścimy link do wylogowania na pasku nawigacyjnym. Ponadto, w celu przetestowania, opublikuj link, który przeniesie Cię do ekranu logowania bez wylogowywania.
<!-- 中略 -->
<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>
<!-- 中略 -->
To tyle, jeśli chodzi o kod MVC.
Potwierdzenie działania
Na tym kończy się minimalna wymagana implementacja uwierzytelniania plików cookie. Spróbuj go uruchomić i zobacz, jak to działa. Zachowanie powinno się zmieniać w zależności od tego, czy jesteś zalogowany, czy nie. Jako prosty przykład możesz zobaczyć następujące zachowanie.
Operacja | ⇒ | wynik działania |
---|---|---|
Idź do domu bez logowania | ⇒ | Przekieruj do ekranu logowania |
login | ⇒ | Przejdź do ekranu głównego |
Wyloguj się ze strony głównej i wróć do domu bez logowania | ⇒ | Przekieruj do ekranu logowania |
Idź do domu bez wylogowywania się z domu i logowania | ⇒ | Przejdź do ekranu głównego |