如何在 asp.net 6.0 中使用 Microsoft Identity Framework 为基于角色的身份验证播种数据
How to seed data for role base authentication using Microsoft Identity Framework in asp.net 6.0
我创建了两个静态 class
DefaultRoles.cs
using DCMS.Web.Constants;
using Microsoft.AspNetCore.Identity;
namespace DCMS.Web.Seeds
{
public class DefaultRoles
{
public static async Task SeedAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
await roleManager.CreateAsync(new IdentityRole(Roles.SuperAdmin.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Admin.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Manager.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.SalesStaff.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Basic.ToString()));
}
}
和我的 DefaultUser.cs Class 赞-
using DCMS.Web.Constants;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
namespace DCMS.Web.Seeds
{
public static class DefaultUsers
{
public static async Task SeedBasicUserAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
// Seed Basic User
var defaultUser = new IdentityUser
{
UserName = "dcmsbasicuser@gmail.com",
Email = "dcmsbasicuser@gmail.com",
EmailConfirmed = true,
PhoneNumberConfirmed = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
{
var user = await userManager.FindByEmailAsync(defaultUser.Email);
if (user == null)
{
await userManager.CreateAsync(defaultUser, "100%Pa$$word");
await userManager.AddToRoleAsync(defaultUser, Roles.Basic.ToString());
}
}
}
public static async Task SeedSuperAdminUserAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
// Seed SuperAdmin User
var defaultUser = new IdentityUser
{
UserName = "dcmssuperadminuser@gmail.com",
Email = "dcmssuperadminuser@gmail.com",
EmailConfirmed = true,
PhoneNumberConfirmed = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
{
var user = await userManager.FindByEmailAsync(defaultUser.Email);
if (user == null)
{
await userManager.CreateAsync(defaultUser, "100%SuperAdminPa$$word");
await userManager.AddToRoleAsync(defaultUser, Roles.Basic.ToString());
await userManager.AddToRoleAsync(defaultUser, Roles.Admin.ToString());
await userManager.AddToRoleAsync(defaultUser, Roles.SuperAdmin.ToString());
}
await roleManager.SeedClaimsForSuperAdmin();
}
}
private static async Task SeedClaimsForSuperAdmin(this RoleManager<IdentityRole> roleManager)
{
var adminRole = await roleManager.FindByNameAsync(Roles.SuperAdmin.ToString());
await roleManager.AddPermissionClaim(adminRole, "Products");
}
public static async Task AddPermissionClaim(this RoleManager<IdentityRole> roleManager, IdentityRole role, string module)
{
var allClaims = await roleManager.GetClaimsAsync(role);
var allPermissions = Permissions.GeneratePermissionsForModule(module);
foreach (var permission in allPermissions)
{
if(!allClaims.Any(a => a.Type=="Permission" && a.Value == permission))
{
await roleManager.AddClaimAsync(role, new Claim("Permission", permission));
}
}
}
}
}
现在我想将那些 class 注入 program.cs class。我的 program.cs class 喜欢-
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DCMS.Web.Data;
using DCMS.Web.Seeds;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Serilog.Events;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
containerBuilder
.RegisterModule(new WebModule());
});
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Host.UseSerilog((ctx, lc) => lc
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.ReadFrom.Configuration(builder.Configuration));
try
{
var app = builder.Build();
Log.Information("Application Starting up");
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
我该怎么办?基本上我想从那些 class 中播种数据以进行用户身份验证。我正在使用 asp.net 6.0。请帮我解决问题
只需将此代码添加到 program.cs 文件
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await DefaultRoles.SeedAsync(userManager, roleManager);
await DefaultUsers.SeedBasicUserAsync(userManager, roleManager);
await DefaultUsers.SeedSuperAdminUserAsync(userManager, roleManager);
Log.Information("Identity User Data Seeding finished");
}
catch (Exception)
{
throw;
}
}
现在program.cs文件会变成这样-
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DCMS.Web.Data;
using DCMS.Web.Seeds;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Serilog.Events;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
containerBuilder
.RegisterModule(new WebModule());
});
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Host.UseSerilog((ctx, lc) => lc
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.ReadFrom.Configuration(builder.Configuration));
try
{
var app = builder.Build();
Log.Information("Application Starting up");
// Need to add for data seeding Start
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await DefaultRoles.SeedAsync(userManager, roleManager);
await DefaultUsers.SeedBasicUserAsync(userManager, roleManager);
await DefaultUsers.SeedSuperAdminUserAsync(userManager, roleManager);
Log.Information("Identity User Data Seeding finished");
}
catch (Exception)
{
throw;
}
}
// Need to add for data seeding End
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
我创建了两个静态 class DefaultRoles.cs
using DCMS.Web.Constants;
using Microsoft.AspNetCore.Identity;
namespace DCMS.Web.Seeds
{
public class DefaultRoles
{
public static async Task SeedAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
await roleManager.CreateAsync(new IdentityRole(Roles.SuperAdmin.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Admin.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Manager.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.SalesStaff.ToString()));
await roleManager.CreateAsync(new IdentityRole(Roles.Basic.ToString()));
}
}
和我的 DefaultUser.cs Class 赞-
using DCMS.Web.Constants;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
namespace DCMS.Web.Seeds
{
public static class DefaultUsers
{
public static async Task SeedBasicUserAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
// Seed Basic User
var defaultUser = new IdentityUser
{
UserName = "dcmsbasicuser@gmail.com",
Email = "dcmsbasicuser@gmail.com",
EmailConfirmed = true,
PhoneNumberConfirmed = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
{
var user = await userManager.FindByEmailAsync(defaultUser.Email);
if (user == null)
{
await userManager.CreateAsync(defaultUser, "100%Pa$$word");
await userManager.AddToRoleAsync(defaultUser, Roles.Basic.ToString());
}
}
}
public static async Task SeedSuperAdminUserAsync(UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager)
{
// Seed SuperAdmin User
var defaultUser = new IdentityUser
{
UserName = "dcmssuperadminuser@gmail.com",
Email = "dcmssuperadminuser@gmail.com",
EmailConfirmed = true,
PhoneNumberConfirmed = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
{
var user = await userManager.FindByEmailAsync(defaultUser.Email);
if (user == null)
{
await userManager.CreateAsync(defaultUser, "100%SuperAdminPa$$word");
await userManager.AddToRoleAsync(defaultUser, Roles.Basic.ToString());
await userManager.AddToRoleAsync(defaultUser, Roles.Admin.ToString());
await userManager.AddToRoleAsync(defaultUser, Roles.SuperAdmin.ToString());
}
await roleManager.SeedClaimsForSuperAdmin();
}
}
private static async Task SeedClaimsForSuperAdmin(this RoleManager<IdentityRole> roleManager)
{
var adminRole = await roleManager.FindByNameAsync(Roles.SuperAdmin.ToString());
await roleManager.AddPermissionClaim(adminRole, "Products");
}
public static async Task AddPermissionClaim(this RoleManager<IdentityRole> roleManager, IdentityRole role, string module)
{
var allClaims = await roleManager.GetClaimsAsync(role);
var allPermissions = Permissions.GeneratePermissionsForModule(module);
foreach (var permission in allPermissions)
{
if(!allClaims.Any(a => a.Type=="Permission" && a.Value == permission))
{
await roleManager.AddClaimAsync(role, new Claim("Permission", permission));
}
}
}
}
}
现在我想将那些 class 注入 program.cs class。我的 program.cs class 喜欢-
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DCMS.Web.Data;
using DCMS.Web.Seeds;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Serilog.Events;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
containerBuilder
.RegisterModule(new WebModule());
});
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Host.UseSerilog((ctx, lc) => lc
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.ReadFrom.Configuration(builder.Configuration));
try
{
var app = builder.Build();
Log.Information("Application Starting up");
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
我该怎么办?基本上我想从那些 class 中播种数据以进行用户身份验证。我正在使用 asp.net 6.0。请帮我解决问题
只需将此代码添加到 program.cs 文件
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await DefaultRoles.SeedAsync(userManager, roleManager);
await DefaultUsers.SeedBasicUserAsync(userManager, roleManager);
await DefaultUsers.SeedSuperAdminUserAsync(userManager, roleManager);
Log.Information("Identity User Data Seeding finished");
}
catch (Exception)
{
throw;
}
}
现在program.cs文件会变成这样-
using Autofac;
using Autofac.Extensions.DependencyInjection;
using DCMS.Web.Data;
using DCMS.Web.Seeds;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Serilog.Events;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => {
containerBuilder
.RegisterModule(new WebModule());
});
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Host.UseSerilog((ctx, lc) => lc
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.ReadFrom.Configuration(builder.Configuration));
try
{
var app = builder.Build();
Log.Information("Application Starting up");
// Need to add for data seeding Start
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await DefaultRoles.SeedAsync(userManager, roleManager);
await DefaultUsers.SeedBasicUserAsync(userManager, roleManager);
await DefaultUsers.SeedSuperAdminUserAsync(userManager, roleManager);
Log.Information("Identity User Data Seeding finished");
}
catch (Exception)
{
throw;
}
}
// Need to add for data seeding End
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}