asp.net coreのデフォルトのWebサイトテンプレートを使用しており、認証は個々のユーザーアカウントを選択しています。ロールを作成してユーザーに割り当て、コントローラでロールを使用してアクセスをフィルタリングできるようにするにはどうすればよいでしょうか。
私のコメントが削除されたのは、私が答えた同様の質問ここへのリンクを提供したからです。そのため、今回はより具体的にお答えします。それではどうぞ。
スタートアップ」クラスに「CreateRoles」メソッドを作成することで、簡単に実現できます。これは、アプリケーションの起動時に、ロールが作成されているかどうかをチェックし、作成されていなければロールを作成します。 こんな感じです。
private async Task CreateRoles(IServiceProvider serviceProvider)
{
//initializing custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
string[] roleNames = { "Admin", "Manager", "Member" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
//create the roles and seed them to the database: Question 1
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
//Here you could create a super user who will maintain the web app
var poweruser = new ApplicationUser
{
UserName = Configuration["AppSettings:UserName"],
Email = Configuration["AppSettings:UserEmail"],
};
//Ensure you have these values in your appsettings.json file
string userPWD = Configuration["AppSettings:UserPassword"];
var _user = await UserManager.FindByEmailAsync(Configuration["AppSettings:AdminUserEmail"]);
if(_user == null)
{
var createPowerUser = await UserManager.CreateAsync(poweruser, userPWD);
if (createPowerUser.Succeeded)
{
//here we tie the new user to the role
await UserManager.AddToRoleAsync(poweruser, "Admin");
}
}
}
とすると、StartupクラスのConfigure
メソッドからCreateRoles(serviceProvider).Wait();
メソッドを呼び出すことができます。
のようにして、StartupクラスのConfigureメソッドから、CreateRoles(serviceProvider).Wait(;
)メソッドを呼び出すことができます。
コントローラでロールベースの承認を使用して、ユーザーのアクセスをフィルタリングします。質問2
次のように簡単にできます。
[Authorize(Roles="Manager")]
public class ManageController : Controller
{
//....
}
のように、アクションメソッドでロールベースの認証を行うこともできます。複数のロールを割り当てることができます。
[Authorize(Roles="Admin, Manager")]
public IActionResult Index()
{
/*
.....
*/
}
この方法でも問題はありませんが、より良い方法として、ポリシーベースのロールチェックを使用することをお勧めします。ASP.NET core のドキュメント ここや、私が書いたこの記事 ここを参照してください。
アカウントコントローラに、ロールを作成する関数を呼び出すアクションを作成し、デフォルトユーザーにadminロールを影響させました(本番ではデフォルトユーザーを削除すべきでしょう)。
private async Task createRolesandUsers()
{
bool x = await _roleManager.RoleExistsAsync("Admin");
if (!x)
{
// first we create Admin rool
var role = new IdentityRole();
role.Name = "Admin";
await _roleManager.CreateAsync(role);
//Here we create a Admin super user who will maintain the website
var user = new ApplicationUser();
user.UserName = "default";
user.Email = "[email protected]";
string userPWD = "somepassword";
IdentityResult chkUser = await _userManager.CreateAsync(user, userPWD);
//Add default User to Role Admin
if (chkUser.Succeeded)
{
var result1 = await _userManager.AddToRoleAsync(user, "Admin");
}
}
// creating Creating Manager role
x = await _roleManager.RoleExistsAsync("Manager");
if (!x)
{
var role = new IdentityRole();
role.Name = "Manager";
await _roleManager.CreateAsync(role);
}
// creating Creating Employee role
x = await _roleManager.RoleExistsAsync("Employee");
if (!x)
{
var role = new IdentityRole();
role.Name = "Employee";
await _roleManager.CreateAsync(role);
}
}
その後、ユーザーのロールを管理するコントローラを作成します。
Temi'さんの回答はほぼ正しいのですが、彼が提案しているように非同期関数から非同期関数を呼び出すことはできません。 そこで、以下のように同期関数の中で非同期呼び出しを行う必要があります。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
CreateRoles(serviceProvider);
}
private void CreateRoles(IServiceProvider serviceProvider)
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
Task<IdentityResult> roleResult;
string email = "[email protected]";
//Check that there is an Administrator role and create if not
Task<bool> hasAdminRole = roleManager.RoleExistsAsync("Administrator");
hasAdminRole.Wait();
if (!hasAdminRole.Result)
{
roleResult = roleManager.CreateAsync(new IdentityRole("Administrator"));
roleResult.Wait();
}
//Check if the admin user exists and create it if not
//Add to the Administrator role
Task<ApplicationUser> testUser = userManager.FindByEmailAsync(email);
testUser.Wait();
if (testUser.Result == null)
{
ApplicationUser administrator = new ApplicationUser();
administrator.Email = email;
administrator.UserName = email;
Task<IdentityResult> newUser = userManager.CreateAsync(administrator, "_AStrongP@ssword!");
newUser.Wait();
if (newUser.Result.Succeeded)
{
Task<IdentityResult> newUserRole = userManager.AddToRoleAsync(administrator, "Administrator");
newUserRole.Wait();
}
}
}
ここで重要なのは、Task<>クラスを使い、同期的な方法で少し異なる方法でシステムを待たせることです。