【T9a】簡易ブログソフトウェアの作成 Part.Ⅰ ~ 認証機能の組み込み(6/14)
プロジェクトタイプ | ASP.NET Core Web アプリ(Model-View-Controller) |
---|
プロジェクト名 | T9a |
---|
ソリューション名 | PIT9 |
---|
ターゲットフレームワーク | .NET 8.0(長期的なサポート) |
---|
最上位レベルのステートメントを使用しない | 使用する(チェックオフ) |
---|
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備作業を参照せよ.
9a-6. 初期ユーザー/グループのためのデータシーディング
次に前章でもやったように初期ユーザーとグループ(ロール)を作成するデータシーディングのためのクラスを作成しよう.
今回は事前に_に示す認証情報を作成することにする.
初期ユーザーとグループ(ロール)名前 | 種別 | 備考 |
---|
administrators | グループ(ロール) | 管理者グループ.AdminRoleName 定数に格納する. |
users | グループ(ロール) | 通常のユーザーグループ.NormalRoleName 定数に格納する. |
admin | ユーザー | 管理者ユーザー.AdminUserName 定数に格納する. 初期パスワードは決め打ちとする. |
プロジェクト内の Data フォルダを右クリックして「追加」→「クラス」をクリックする.
IdentityDataSeeder
(.csは省略可能)と入力して「追加」ボタンをクリックしよう.
すると空のクラス定義が作られるので_の定義を書き込もう.
初期ユーザー作成のためのクラス 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| using Microsoft.AspNetCore.Identity; // 追記
using T9a.Models; // 追記
namespace T9a.Data
{
// 初期ユーザー作成のためのクラス
public class IdentityDataSeeder
{
public const string AdminRoleName = "administrators"; // アプリケーション内で用いる管理者グループの名前(決め打ち)
public const string AdminUserName = "admin"; // アプリケーション内で用いる管理者ユーザーの名前(決め打ち)
public const string NormalRoleName = "users"; // アプリケーション内で用いる通常ユーザーのグループの名前(決め打ち)
public const string AllRoles = "administrators,users"; // すべてのグループをカンマでつないだもの(認証の設定で使う)
// ┌─ ここが前回と異なり IdentityUser ではなく
// │ BlogUser となっている点に注意
// ↓
private readonly UserManager<BlogUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
// コンストラクタ
public IdentityDataSeeder(UserManager<BlogUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
// 初期ユーザー作成のためのメソッド(非同期メソッド版)
public async Task EnsureDefaultCredentialsAsync()
{
if (!await _roleManager.RoleExistsAsync(AdminRoleName)) // 管理者グループが存在していなければ
await _roleManager.CreateAsync(new IdentityRole(AdminRoleName)); // それを作成する.
if (!await _roleManager.RoleExistsAsync(NormalRoleName)) // 通常ユーザーのグループが存在していなければ
await _roleManager.CreateAsync(new IdentityRole(NormalRoleName)); // それを作成する.
var user = await _userManager.FindByNameAsync(AdminUserName); // 管理者ユーザーが存在するかどうかを確認する.
if (user == null) // 存在しない場合.
{
user = new BlogUser()
{
UserName = AdminUserName,
SecurityStamp = Guid.NewGuid().ToString("D"),
Nickname = AdminUserName,
Email = "admin@example.com",
Registered = DateTime.Now
};
await _userManager.CreateAsync(user, "p@55W0rD"); // 管理者の初期パスワードは
await _userManager.AddToRoleAsync(user, AdminRoleName); // 決め打ちにする.
}// if
}
// 初期ユーザー作成のためのメソッド(同期メソッド版)
public void EnsureDefaultCredentials()
{
EnsureDefaultCredentialsAsync().Wait();
}
// Program.cs から呼び出して認証情報を作成するための静的メソッド
public static void SeedData(IHost app)
{
var factory = app.Services.GetService<IServiceScopeFactory>();
using (var scope = factory!.CreateScope())
{
var dataSeeder = scope.ServiceProvider.GetService<IdentityDataSeeder>();
dataSeeder!.EnsureDefaultCredentials();
}
}
}
}
|
前節とおおむね同じだが,違う部分はユーザーの管理のためのジェネリッククラスUserManager<TUser>
のジェネリックパラメーターTUser
に
IdentityUser
ではなく本節で定義したユーザークラスBlogUser
を指定している点である.本節のように「ユーザー」として使用するクラスを
拡張する場合は,UserManager<TUser>
ジェネリッククラスやSignInManager<TUser>
ジェネリッククラスのTUser
の部分には
自分で定義した「ユーザー」用のクラスを指定する必要がある.
次に, Program.cs に_に示す内容を追記しよう.
Program.csの追記内容 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| using KnzwTech.AspNetCore.ResourceBasedLocalization;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity; // 追記
using T9a.Data;
using T9a.Models; // 追記
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews(opt => opt.EnableDefaultErrorMessagesFromResource());
builder.Services.AddDbContext<T9aContext>(
opt => opt.UseNpgsql(builder.Configuration.GetConnectionString(nameof(T9aContext))));
// ┌─ ここが前回と異なり IdentityUser ではなく
// │ BlogUser となっている点に注意
// ↓
builder.Services.AddIdentity<BlogUser, IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<T9aContext>();
builder.Services.ConfigureApplicationCookie(opt => {
opt.LoginPath = "/Accounts/Login";
opt.LogoutPath = "/Accounts/Logout";
opt.AccessDeniedPath = "/Accounts/AccessDenied";
});
builder.Services.AddTransient<IdentityDataSeeder>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseStatusCodePagesWithReExecute("/Home/AccessError/{0}");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
IdentityDataSeeder.SeedData(app);
app.Run();
|
Last updated on 2024-06-19
Published on 2024-06-19