【发布时间】:2016-11-18 22:08:09
【问题描述】:
虽然似乎有很多关于使用 ASP.NET Core 验证角色、声明等的文档,但很少有关于在我的应用程序中初始设置这些内容的信息。
【问题讨论】:
标签: c# asp.net-mvc asp.net-core asp.net-identity
虽然似乎有很多关于使用 ASP.NET Core 验证角色、声明等的文档,但很少有关于在我的应用程序中初始设置这些内容的信息。
【问题讨论】:
标签: c# asp.net-mvc asp.net-core asp.net-identity
配置角色、声明等的最佳方式是在您的应用启动中。如果您知道自己在做什么,那么新的 ASP.NET Core 依赖注入使设置变得轻而易举。您的大部分工作将在项目根目录下的 Startup.cs 文件中进行。
不要通过将您的新用户机密硬编码到可以共享的存储库中来与全世界分享。幸运的是,微软为此提供了一个很好的工具。本文详细讲解:Safe Storage of App Secrets
为确保此服务稍后可用,请检查 Startup.cs 中的 Startup 构造函数方法:
public Startup(IHostingEnvironment env) {
...
if (env.IsDevelopment()) {
// BELOW IS THE IMPORTANT LINE
builder.AddUserSecrets();
}
...
// This is important, too. It sets up a readonly property
// that you can use to access your user secrets.
Configuration = builder.Build();
}
// This is the read-only property
public IConfigurationRoot Configuration { get; }
我将 Entity Framework Core 用于我的持久性存储。当我使用 Web App 模板创建我的应用程序时,会自动生成此代码。但我会将其包含在此处以供参考和故障排除(仍在Startup.cs):
public void ConfigureServices(IServiceCollection services)
{
// My Db Context is named "ApplicationDbContext", which is the
// default name. Yours might be something different.
// Additionally, if you're using a persistence store other than
// MSSQL Server, you might have a different set of options here.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// This sets up the basics of the Identity code. "ApplicationUser"
// is the name of the model that I use for my basic user. It's simply
// a POCO that can be modified like any EF model, and it's the default
// name for a user in the template. "ApplicationRole" is a class that I
// wrote that inherits from the "IdentityRole" base class. I use it to
// add a role description, and any other future data I might want to
// include with my role. I then tell the Identity code to store it's
// data in the "ApplicationDbContext" that I just setup.
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProvider();
// This sets up the MVC framework.
services.AddMvc();
...
}
Configure 方法中创建钩子这是真正的工作开始的地方。您需要配置一个具有完全管理权限的角色并将第一个用户分配给该角色。我选择将该代码放在Startup.cs 中的私有方法中,我从Configure 方法中调用该方法。一、调用代码:
// This method is not async out-of-the-box. Add the `async` modifier
// but keep the return type as `void`, since the signature needs to
// stay the same or you'll get a 500 error. We mark it as async because
// the Identity methods are mostly async methods.
public async void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
...
// Default ASP.NET Core route (generated out of the box)
// I've included this so you know where to put your code!
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// Her, we call the code that setups up our roles and our first user.
// These are methods added to the `Startup` class. We use the
// IApplicationBuilder variable to pass in a User and Role
// Manager instance from the application services.
await CreateRoles(
app.ApplicationServices
.GetRequiredService<RoleManager<ApplicationRole>>());
await ConfigureSiteAdmin(
app.ApplicationServices
.GetRequiredService<RoleManager<ApplicationRole>>(),
app.ApplicationServices
.GetRequiredService<UserManager<ApplicationUser>>()
);
}
我发现设置一个存储我的角色名称的静态类很有用。这使我可以在编译时检查名称,并在我需要在其他地方调用角色名称时在整个代码中为我提供 Intellisense 帮助。它看起来像这样:
public static class RoleNames
{
public const string SiteAdmin = "Site Admin";
public const string CompanyAdmin = "Company Admin";
...
}
完成之后,现在我们可以设置我们的角色了。请记住,我使用ApplicationUser 作为我的用户类型和ApplicationRole 作为我的角色类型。你可以用不同的名字命名你的。将这些方法添加到Startup.cs 文件的底部:
private async Task CreateRoles(RoleManager<ApplicationRole> roleManager)
{
var roles = new List<ApplicationRole>
{
// These are just the roles I made up. You can make your own!
new ApplicationRole {Name = RoleName.SiteAdmin,
Description = "Full access to all features."},
new ApplicationRole {Name = RoleName.CompanyAdmin,
Description = "Full access to features within their company."}
};
foreach (var role in roles)
{
if (await roleManager.RoleExistsAsync(role.Name)) continue;
var result = await roleManager.CreateAsync(role);
if (result.Succeeded) continue;
// If we get here, something went wrong.
throw new Exception($"Could not create '{role.Name}' role.");
}
}
现在我们设置用于创建管理员的方法。我们检查以确保用户还不存在。用户名是使用上面提到的 dotnet 用户机密存储的。我们还检查以确保我们的主要管理员角色已创建,以便我们可以立即将此用户分配给该角色。
private async Task ConfigureSiteAdmin(
RoleManager<ApplicationRole> roleManager,
UserManager<ApplicationUser> userManager)
{
if (await userManager.FindByEmailAsync(Configuration["SiteAdminEmail"]) != null)
return;
if (!await roleManager.RoleExistsAsync(RoleName.SiteAdmin))
throw new Exception($"The {RoleName.SiteAdmin} role has not yet been created.");
var user = new ApplicationUser
{
UserName = Configuration["SiteAdminEmail"],
Email = Configuration["SiteAdminEmail"],
};
await userManager.CreateAsync(user, Configuration["SiteAdminPassword"]);
await userManager.AddToRoleAsync(user, RoleName.SiteAdmin);
}
我希望这对您有所帮助。我花了很长时间才找到散布在网络上的所有这些信息。如果您有任何改进建议,请告诉我!
【讨论】: