如何将基于角色的身份添加到 Razor Pages 应用程序?
How to add identity based on roles to Razor Pages app?
我正在设置一个新的 Razor Pages 应用,我想添加基于角色的授权。网上有很多教程如何使用 ASP.NET MVC 应用程序而不是 Razor 页面。我尝试了很少的解决方案,但对我没有任何用处。目前我有一个问题如何为数据库添加角色并将这个角色添加到每个新注册用户。
这是我的 Startup.cs
的样子:
public async Task ConfigureServices(IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
})
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthorization(config =>
{
config.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages()
.AddNewtonsoftJson()
.AddRazorPagesOptions(options => {
options.Conventions.AuthorizePage("/Privacy", "Administrator");
});
await CreateRolesAsync(serviceProvider);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/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.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
/// <summary>
/// Method that creates roles
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
private async Task CreateRolesAsync(IServiceProvider serviceProvider)
{
//adding custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Admin", "Member", "Outcast" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
//creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
现在这段代码抛出异常:
System.InvalidOperationException: 'Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorizationPolicyEvaluator' inside the call to 'ConfigureServices(...)' in the application startup code.'
添加 AddAuthorizationPolicyEvaluator
没有任何改变。
有什么建议吗?
好的,我只是让我的应用程序正常工作 :) 我想我只是 post 在这里我的 Startup.cs
代码用于未来的问题 - 也许它会对某人有所帮助。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
})
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthorization(config =>
{
config.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
config.AddPolicy("RequireMemberRole",
policy => policy.RequireRole("Member"));
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages()
.AddNewtonsoftJson()
.AddRazorPagesOptions(options => {
options.Conventions.AuthorizePage("/Privacy", "RequireAdministratorRole");
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, UserManager<IdentityUser> userManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/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.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
CreateDatabase(app);
CreateRolesAsync(serviceProvider).Wait();
CreateSuperUser(userManager).Wait();
}
private async Task CreateSuperUser(UserManager<IdentityUser> userManager)
{
var superUser = new IdentityUser { UserName = Configuration["SuperUserLogin"], Email = Configuration["SuperUserLogin"] };
await userManager.CreateAsync(superUser, Configuration["SuperUserPassword"]);
var token = await userManager.GenerateEmailConfirmationTokenAsync(superUser);
await userManager.ConfirmEmailAsync(superUser, token);
await userManager.AddToRoleAsync(superUser, "Admin");
}
private void CreateDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
context.Database.EnsureCreated();
}
}
private async Task CreateRolesAsync(IServiceProvider serviceProvider)
{
//adding custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Admin", "Member", "Outcast" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
//creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
}
通常,应用程序在启动时只是创建新数据库,添加 "Admin"、"Member" 和 "Outcast" 角色,最后根据用户机密凭据创建超级用户帐户。
另外,在 Register.cshtml.cs
文件中,我有一行将默认角色 "Member" 添加到新成员
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
await _userManager.AddToRoleAsync(user, "Member");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email to get acces to Functionality Matrix pages",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
// Block autologin after registration
//await _signInManager.SignInAsync(user, isPersistent: false);
return Redirect("./ConfirmEmailInfo");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}
我正在设置一个新的 Razor Pages 应用,我想添加基于角色的授权。网上有很多教程如何使用 ASP.NET MVC 应用程序而不是 Razor 页面。我尝试了很少的解决方案,但对我没有任何用处。目前我有一个问题如何为数据库添加角色并将这个角色添加到每个新注册用户。
这是我的 Startup.cs
的样子:
public async Task ConfigureServices(IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
})
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthorization(config =>
{
config.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages()
.AddNewtonsoftJson()
.AddRazorPagesOptions(options => {
options.Conventions.AuthorizePage("/Privacy", "Administrator");
});
await CreateRolesAsync(serviceProvider);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/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.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
/// <summary>
/// Method that creates roles
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
private async Task CreateRolesAsync(IServiceProvider serviceProvider)
{
//adding custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Admin", "Member", "Outcast" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
//creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
现在这段代码抛出异常:
System.InvalidOperationException: 'Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorizationPolicyEvaluator' inside the call to 'ConfigureServices(...)' in the application startup code.'
添加 AddAuthorizationPolicyEvaluator
没有任何改变。
有什么建议吗?
好的,我只是让我的应用程序正常工作 :) 我想我只是 post 在这里我的 Startup.cs
代码用于未来的问题 - 也许它会对某人有所帮助。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
})
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthorization(config =>
{
config.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
config.AddPolicy("RequireMemberRole",
policy => policy.RequireRole("Member"));
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages()
.AddNewtonsoftJson()
.AddRazorPagesOptions(options => {
options.Conventions.AuthorizePage("/Privacy", "RequireAdministratorRole");
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, UserManager<IdentityUser> userManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/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.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
CreateDatabase(app);
CreateRolesAsync(serviceProvider).Wait();
CreateSuperUser(userManager).Wait();
}
private async Task CreateSuperUser(UserManager<IdentityUser> userManager)
{
var superUser = new IdentityUser { UserName = Configuration["SuperUserLogin"], Email = Configuration["SuperUserLogin"] };
await userManager.CreateAsync(superUser, Configuration["SuperUserPassword"]);
var token = await userManager.GenerateEmailConfirmationTokenAsync(superUser);
await userManager.ConfirmEmailAsync(superUser, token);
await userManager.AddToRoleAsync(superUser, "Admin");
}
private void CreateDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
context.Database.EnsureCreated();
}
}
private async Task CreateRolesAsync(IServiceProvider serviceProvider)
{
//adding custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Admin", "Member", "Outcast" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
//creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
}
通常,应用程序在启动时只是创建新数据库,添加 "Admin"、"Member" 和 "Outcast" 角色,最后根据用户机密凭据创建超级用户帐户。
另外,在 Register.cshtml.cs
文件中,我有一行将默认角色 "Member" 添加到新成员
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
await _userManager.AddToRoleAsync(user, "Member");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email to get acces to Functionality Matrix pages",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
// Block autologin after registration
//await _signInManager.SignInAsync(user, isPersistent: false);
return Redirect("./ConfirmEmailInfo");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}