【T9a】簡易ブログソフトウェアの作成 Part.Ⅰ ~ 認証機能の組み込み(12/14)
プロジェクトタイプ | ASP.NET Core Web アプリ(Model-View-Controller) |
---|
プロジェクト名 | T9a |
---|
ソリューション名 | PIT9 |
---|
ターゲットフレームワーク | .NET 8.0(長期的なサポート) |
---|
最上位レベルのステートメントを使用しない | 使用する(チェックオフ) |
---|
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備作業を参照せよ.
9a-12. ユーザーの詳細情報の表示
つぎにユーザーの詳細情報を表示するUserDetails
アクションを実装しよう.
Controllers/AccountsController.cs のAccountsController
クラスに_に示す内容を追記しよう.
Accountsコントローラーの追記内容(UserDetails) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| // UserDetailsアクション(GETのみ)
[Authorize(Roles = IdentityDataSeeder.AllRoles)]
public async Task<IActionResult> UserDetails(string? id) // 引数名はルーティングパラメーター名と一致している必要がある.
{
if (string.IsNullOrEmpty(id)) // ルーティングパラメーターが指定されていなければ
return NotFound(); // 404 Not Found を返す.
var userName = id; // ルーティングパラメーターには実際には
// ユーザー名が格納されている(Idではない)
var targetUser = await _userManager.FindByNameAsync(userName); // 指定されたユーザー名から,表示対象のユーザー情報を検索する.
if (targetUser == null) // 見つからなければ
return NotFound(); // 404 Not Found を返す.
var currentUser = await _userManager.GetUserAsync(User); // 現在ログイン中のユーザー情報を取得して
bool isAdminUser = await IsAdminUserAsync(currentUser); // それが管理者ユーザーかどうかを調べる.
if (!(isAdminUser || targetUser.Id == currentUser!.Id)) // 管理者ユーザーであるか,もしくは
return Forbid(); // 表示対象がログインしているユーザー自身である場合以外は,
// アクセスを拒否する.
return View(targetUser);
}
|
リスト9a-9-2で言及した通り,ルーティングパラメーターid
にはユーザーIDではなくユーザー名(UserName
)を使ったリンクを作成してるため,
UserDetails()
メソッドの引数にはユーザー名が渡されている点に注意しよう.ここではUserManager<TUser>
クラスの
.FindByNameAsync()を
使ってユーザー名を格納した文字列から,対応するユーザーのBlogUser
オブジェクトを検索している.
ここで16~21行目ではログイン中のユーザー情報を取得して,通常ユーザーが自分自身以外を表示しようとしているときはForbid()
メソッドを呼び出して
アクセスを拒否している.Forbid()
メソッドメソッドは,要求されたリソースへのアクセスが禁じられていることを示すHTTPのレスポンスコード
403 Forbidden
をクライアントに返却するためのメソッドである.
次にこのUserDetails
アクションのためのビューを作成しよう.
Views/Accounts/UserDetails.cshtml を_のように記述する.
Views/Accounts/UserDetails.cshtmlの内容 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| @model BlogUser
@{
ViewData["Title"] = "ユーザー詳細";
if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策
}
<table>
<tr><th>項目</th><th>値</th></tr>
@* ユーザー名(Username)の表示 *@
<tr>
<td>@Html.DisplayNameFor(u => u.UserName)</td>
<td>@Html.DisplayFor(u => u.UserName)</td>
</tr>
@* ニックネーム(Nickname)の表示 *@
<tr>
<td>@Html.DisplayNameFor(u => u.Nickname)</td>
<td>@Html.DisplayFor(u => u.Nickname)</td>
</tr>
@* メールアドレス(Email)の表示 *@
<tr>
<td>@Html.DisplayNameFor(u => u.Email)</td>
<td>@Html.DisplayFor(u => u.Email)</td>
</tr>
@* 登録日時(Registered)の表示 *@
<tr>
<td>@Html.DisplayNameFor(u => u.Registered)</td>
<td>@Html.DisplayFor(u => u.Registered)</td>
</tr>
</table>
<a asp-action="EditUser" asp-route-id="@Model.UserName">編集</a>
| <a asp-action="DeleteUser" asp-route-id="@Model.UserName">退会(削除)</a>
|
このビューでも特に変わったことはしていない.
これでユーザー詳細画面ができたので,LoginRoute
アクションとAddUser
アクションにおける遷移先を修正しておこう.
Controllers/AccountController.cs のLoginRoute()
メソッドおよびAddUser()
メソッド(POST用)を
それぞれ_,_に示すように変更する.
Accountsコントローラーの変更内容(LoginRoute) 1
2
3
4
5
6
7
8
9
10
11
| // LoginRouteアクション(遷移先の振り分け用),認証済みなら誰でもアクセス可
[Authorize(Roles = IdentityDataSeeder.AllRoles)]
public async Task<IActionResult> LoginRoute()
{
var user = await _userManager.GetUserAsync(User);
if (await IsAdminUserAsync(user))
return RedirectToAction(nameof(Index));
else
return RedirectToAction(nameof(UserDetails), new { id = user!.UserName }); // ユーザー詳細画面へ遷移する.
}
|
Accountsコントローラーの変更内容(AddUser) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| // AddUserアクション(POST用)
[Authorize(Roles = IdentityDataSeeder.AdminRoleName)]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddUser(NewUserInfo newUserInfo)
{
if (ModelState.IsValid)
{
var user = new BlogUser()
{
UserName = newUserInfo.Username,
Nickname = newUserInfo.Nickname,
Email = newUserInfo.Email,
Registered = DateTime.Now,
SecurityStamp = Guid.NewGuid().ToString("D")
};
try
{
var res1 = await _userManager.CreateAsync(user, newUserInfo.Password);
if (!res1.Succeeded) throw new IdentityOperationFailedException(res1);
var res2 = await _userManager.AddToRoleAsync(user, IdentityDataSeeder.NormalRoleName);
if (!res2.Succeeded) throw new IdentityOperationFailedException(res2);
return RedirectToAction(nameof(UserDetails), new { id = user.UserName }); // ユーザー詳細画面へ遷移する.
}
catch (CompositeMessagesException ex)
{
ViewBag.ErrorMessages = ex.ErrorMessages;
}
}//if
return View(newUserInfo);
}
|
ここまで書けたら実行してみよう.プロジェクトを起動して「ログイン」のリンクをクリックしadmin
として
ログインしよう.起動時にログイン済みの場合は画面上部の「ユーザー一覧」のリンクをクリックして
ユーザー一覧画面(Index
)を表示させ,適当なユーザーのリンクをクリックしてみよう.
クリックしたユーザーのユーザー名,ニックネーム,メールアドレスといった詳細情報が表示されるはずである(_).
また,ユーザー一覧画面に戻り「新規ユーザー登録」のリンクをクリックして適当にユーザーを作成しよう.ユーザー一覧画面ではなく
ユーザー詳細画面に遷移するはずである(_).
実行結果Last updated on 2024-06-19
Published on 2024-06-19