如何在 Asp.net Identity 3.0 和 MVC 6 中启用角色?
How to turn on Roles in Asp.net Identity 3.0 and MVC 6?
我不确定我是否遗漏了什么。默认情况下 User.IsInRole()
不工作,即使用户确实有一些角色。
我没有自己的角色存储实现。我假设默认的应该有效。我需要在 Startup.cs
中做一些特别的事情来让角色发挥作用吗?我正在使用 mvc 6 beta 2 默认模板。
如果我添加这样的角色,User.IsInRole()
将不起作用:
await UserManager.AddToRoleAsync(user, "Admin");
但如果我这样做确实有效:
await UserManager.AddClaimAsync(user, claim: new Claim(ClaimTypes.Role.ToString(), "Admin"));
您似乎在使用 Asp.NET Identity 和最新的 ASP.NET 5 个东西。我正在使用相同的(当前使用 RC1)。我遇到了类似的问题,经过一番挖掘,我找到了使用 SignInManager
的 RefreshSignInAsync()
方法的解决方案。
请注意,为了获取 UserManager
和 SignInManager
的实例,我使用了依赖注入,因此我的控制器的构造函数如下所示:
public MyController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
我的要求是,如果一个特定的控制器方法被一个经过身份验证的用户访问,那么一个角色将被添加到该用户,如果该用户还没有那个角色,并且它需要立即生效。 (在控制器和视图中对 User.IsInRole("TheRole")
的后续调用需要 return true,用户无需注销并重新登录)。
操作如下:
[AllowAnonymous]
public async Task<IActionResult> CreateProfile()
{
if (User == null || User.Identity == null || !User.Identity.IsAuthenticated)
{
return RedirectToAction("RegisterOrSignIn", "Account");
}
else
{
if (!User.IsInRole("TheRole"))
{
ApplicationUser applicationUser =
await _userManager.FindByIdAsync(User.GetUserId());
await _userManager.AddToRoleAsync(applicationUser, "TheRole");
await _signInManager.RefreshSignInAsync(applicationUser);
}
return RedirectToAction("Index");
}
}
注意你需要
using System.Security.Claims;
用于 GetUserId()
扩展方法。
所以我学到的最重要的事情是使用 UserManager
的 AddToRoleAsync
和 SignInManager
的 RefreshSignInAsync
。第一个向 AspNetUserRoles table 添加一行。第二个刷新 cookie,在浏览器发出下一个请求时,将显示用户在该角色中。
顺便说一句,我在 Startup.cs 中添加了一个名为 EnsureRoles()
的方法。我在 Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
中调用 app.UseIdentity()
之后立即调用它。所以,这是来自 Configure()
的片段:
...
// Add cookie-based authentication to the request pipeline.
app.UseIdentity();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
// Ensure roles are in DB - OK not to await this for now
EnsureRoles(app, loggerFactory);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
...
这里是 EnsureRoles()
:
private async Task EnsureRoles(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
ILogger logger = loggerFactory.CreateLogger<Startup>();
RoleManager<IdentityRole> roleManager = app.ApplicationServices.GetService<RoleManager<IdentityRole>>();
string[] roleNames = { "TheRole", "AnotherRole" };
foreach (string roleName in roleNames)
{
bool roleExists = await roleManager.RoleExistsAsync(roleName);
if (!roleExists)
{
logger.LogInformation(String.Format("!roleExists for roleName {0}", roleName));
IdentityRole identityRole = new IdentityRole(roleName);
IdentityResult identityResult = await roleManager.CreateAsync(identityRole);
if (!identityResult.Succeeded)
{
logger.LogCritical(
String.Format(
"!identityResult.Succeeded after
roleManager.CreateAsync(identityRole) for
identityRole with roleName {0}",
roleName));
foreach (var error in identityResult.Errors)
{
logger.LogCritical(
String.Format(
"identityResult.Error.Description: {0}",
error.Description));
logger.LogCritical(
String.Format(
"identityResult.Error.Code: {0}",
error.Code));
}
}
}
}
}
我不确定我是否遗漏了什么。默认情况下 User.IsInRole()
不工作,即使用户确实有一些角色。
我没有自己的角色存储实现。我假设默认的应该有效。我需要在 Startup.cs
中做一些特别的事情来让角色发挥作用吗?我正在使用 mvc 6 beta 2 默认模板。
如果我添加这样的角色,User.IsInRole()
将不起作用:
await UserManager.AddToRoleAsync(user, "Admin");
但如果我这样做确实有效:
await UserManager.AddClaimAsync(user, claim: new Claim(ClaimTypes.Role.ToString(), "Admin"));
您似乎在使用 Asp.NET Identity 和最新的 ASP.NET 5 个东西。我正在使用相同的(当前使用 RC1)。我遇到了类似的问题,经过一番挖掘,我找到了使用 SignInManager
的 RefreshSignInAsync()
方法的解决方案。
请注意,为了获取 UserManager
和 SignInManager
的实例,我使用了依赖注入,因此我的控制器的构造函数如下所示:
public MyController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
我的要求是,如果一个特定的控制器方法被一个经过身份验证的用户访问,那么一个角色将被添加到该用户,如果该用户还没有那个角色,并且它需要立即生效。 (在控制器和视图中对 User.IsInRole("TheRole")
的后续调用需要 return true,用户无需注销并重新登录)。
操作如下:
[AllowAnonymous]
public async Task<IActionResult> CreateProfile()
{
if (User == null || User.Identity == null || !User.Identity.IsAuthenticated)
{
return RedirectToAction("RegisterOrSignIn", "Account");
}
else
{
if (!User.IsInRole("TheRole"))
{
ApplicationUser applicationUser =
await _userManager.FindByIdAsync(User.GetUserId());
await _userManager.AddToRoleAsync(applicationUser, "TheRole");
await _signInManager.RefreshSignInAsync(applicationUser);
}
return RedirectToAction("Index");
}
}
注意你需要
using System.Security.Claims;
用于 GetUserId()
扩展方法。
所以我学到的最重要的事情是使用 UserManager
的 AddToRoleAsync
和 SignInManager
的 RefreshSignInAsync
。第一个向 AspNetUserRoles table 添加一行。第二个刷新 cookie,在浏览器发出下一个请求时,将显示用户在该角色中。
顺便说一句,我在 Startup.cs 中添加了一个名为 EnsureRoles()
的方法。我在 Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
中调用 app.UseIdentity()
之后立即调用它。所以,这是来自 Configure()
的片段:
...
// Add cookie-based authentication to the request pipeline.
app.UseIdentity();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
// Ensure roles are in DB - OK not to await this for now
EnsureRoles(app, loggerFactory);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
...
这里是 EnsureRoles()
:
private async Task EnsureRoles(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
ILogger logger = loggerFactory.CreateLogger<Startup>();
RoleManager<IdentityRole> roleManager = app.ApplicationServices.GetService<RoleManager<IdentityRole>>();
string[] roleNames = { "TheRole", "AnotherRole" };
foreach (string roleName in roleNames)
{
bool roleExists = await roleManager.RoleExistsAsync(roleName);
if (!roleExists)
{
logger.LogInformation(String.Format("!roleExists for roleName {0}", roleName));
IdentityRole identityRole = new IdentityRole(roleName);
IdentityResult identityResult = await roleManager.CreateAsync(identityRole);
if (!identityResult.Succeeded)
{
logger.LogCritical(
String.Format(
"!identityResult.Succeeded after
roleManager.CreateAsync(identityRole) for
identityRole with roleName {0}",
roleName));
foreach (var error in identityResult.Errors)
{
logger.LogCritical(
String.Format(
"identityResult.Error.Description: {0}",
error.Description));
logger.LogCritical(
String.Format(
"identityResult.Error.Code: {0}",
error.Code));
}
}
}
}
}