Razor Pagesでアプリケーション独自のアカウントで認証するコードを紹介します。
概要
こちらの記事では、Razor Pagesでのシンプルな認証のアプリケーションを実装しました。
この記事では、シンプルな実装から処理を追加して、アプリケーション独自のアカウントで認証するコードを紹介します。
プログラム例
ASP.NET Core アプリケーションを作成します。
ファイル構成は下図の通りです。
コード
以下のコードを記述します。
@page
@model AuthenticationApp.Pages.Account.LoginModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head></head>
<body>
<h1>ログイン</h1>
<form method="post">
ID:<input type="text" asp-for="InputUserID"/><br/>
Password:<input type="password" asp-for="InputPassword"/><br/>
@if (Model.OutMessage!=""){
<div>@Model.OutMessage</div>
}
<input type="submit" value="ログイン" /><br/>
</form>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
namespace AuthenticationApp.Pages.Account
{
public class LoginModel : PageModel
{
[BindProperty]
public string InputUserID { get; set; }
[BindProperty]
public string InputPassword { get; set; }
public string OutMessage { get; set; } = "";
public void OnGet()
{
}
public IActionResult OnPost(string ReturnUrl)
{
List<UserInfo> userList = new List<UserInfo>();
userList.Add(new UserInfo("penta", "pen123", "ぺんた"));
userList.Add(new UserInfo("tori", "tor123", "とりっち"));
userList.Add(new UserInfo("morgan", "mog123", "もーがん"));
userList.Add(new UserInfo("lucy", "luc123", "るーしー"));
UserInfo authUserInfo = null;
foreach (UserInfo ui in userList) {
if (ui.id == InputUserID && ui.password == InputPassword) {
authUserInfo = ui;
}
}
if (authUserInfo != null) {
Claim[] claims = {
new Claim(ClaimTypes.NameIdentifier, authUserInfo.id),
new Claim(ClaimTypes.Name, authUserInfo.name)
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties {
IsPersistent = true
}
);
if (ReturnUrl == null || ReturnUrl == "") {
return RedirectToPage("/Index");
}
else {
return Redirect(ReturnUrl);
}
}
else {
OutMessage = "IDまたはパスワードが違います。";
return Page();
}
}
}
}
@page
@model AuthenticationApp.Pages.Account.LogoutModel
@{
}
<html>
<head>
</head>
<body>
<h1>Logout</h1>
<p>ログアウトしました。</p>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
namespace AuthenticationApp.Pages.Account
{
public class LogoutModel : PageModel
{
public void OnGet()
{
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
@page
@model AuthenticationApp.Pages.ContentModel
@{
}
<html>
<head>
</head>
<body>
<h1>コンテンツのページ</h1>
<p>ユーザー:@Model.OutUserName</p>
<p>コンテンツのページです</p>
<p>認証が必要なページです</p>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
namespace AuthenticationApp.Pages
{
[Authorize]
public class ContentModel : PageModel
{
public string OutUserName { get; set; }
public void OnGet()
{
foreach (Claim c in User.Claims) {
if (c.Type == ClaimTypes.Name) OutUserName = c.Value;
}
}
}
}
@page
@model AuthenticationApp.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head></head>
<body>
<h1>index</h1>
<a asp-page="/Account/Login">Login</a><br/>
<a asp-page="/Account/Logout">Logout</a><br/>
<a asp-page="/Content">Content</a><br/>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace AuthenticationApp.Pages
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}
using Microsoft.AspNetCore.Authentication.Cookies;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
WebApplication app = builder.Build();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
namespace AuthenticationApp
{
public class UserInfo
{
public string id;
public string password;
public string name;
public UserInfo(string id, string password, string name)
{
this.id = id;
this.password = password;
this.name = name;
}
}
}
解説
ログイン処理、ログアウト処理の基本的な動作は
こちらの記事を参照してください。
今回、ログイン用のアカウントは簡易的な実装になっています。UserInfo オブジェクトのリストを用意し、
UserUnfoオブジェクトを作成し、ユーザーIDやパスワードを設定し、アプリケーションで利用できるアカウントを作成しています。
テキストボックスで入力した、ID、パスワードが一致しているか確認し、一致していれば、認証できたアカウントとして、UserInfo オブジェクトを
authUserInfo 変数に代入します。
ID、パスワード判定の後、authUserInfo 変数がnullでなければ認証できたと判断し、ログイン処理を実行します。
ログイン処理中のClaimオブジェクトには、authUserInfo 変数のUserInfoオブジェクトの値を利用してアカウント情報を記録します。
ログイン成功時には、ReturnUrl パラメーターがある場合は、ReturnUrlにリダイレクトします。
ReturnUrlパラメーターがない場合はトップページの"/Index"にリダイレクトします。
public IActionResult OnPost(string ReturnUrl)
{
List<UserInfo> userList = new List<UserInfo>();
userList.Add(new UserInfo("penta", "pen123", "ぺんた"));
userList.Add(new UserInfo("tori", "tor123", "とりっち"));
userList.Add(new UserInfo("morgan", "mog123", "もーがん"));
userList.Add(new UserInfo("lucy", "luc123", "るーしー"));
UserInfo authUserInfo = null;
foreach (UserInfo ui in userList) {
if (ui.id == InputUserID && ui.password == InputPassword) {
authUserInfo = ui;
}
}
if (authUserInfo != null) {
/* ログイン処理 */
if (ReturnUrl == null || ReturnUrl == "") {
return RedirectToPage("/Index");
}
else {
return Redirect(ReturnUrl);
}
}
else {
OutMessage = "IDまたはパスワードが違います。";
return Page();
}
}
実行結果
プロジェクトを実行し、アプリケーションルートのURLにアクセスします。
下図のページが表示されます。
[Content]のリンクをクリックします。未ログイン状態の場合、リダイレクトされ、ログイン画面が表示されます。
IDとパスワードを入力します。入力後[ログイン]ボタンをクリックします。
コンテンツページが表示されます。ログインしたユーザー名が表示されることが確認できます。
トップページに戻り、[Logout]リンクをクリックします。ログアウトメッセージが表示されます。
再度ログイン画面にアクセスし、別のID、パスワードでログインします。
コンテンツのページにアクセスすると、ユーザー名がログインした別のユーザー名に変わることが確認できます。
ログアウトし、別のユーザーでログインしますが、IDやパスワードを間違えます。
IDを間違えるとログインできず、エラーメッセージが画面に表示されます。
正しいIDとパスワードでログインできると、ログインしたユーザー名が表示されます。
アプリケーション独自のアカウントでの認証を実装できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-08-05
作成日: 2022-08-05