问题
I am not sure if I am missing something here. By Default User.IsInRole()
does not work even if user DOES HAVE some roles.
I don't have my own implementation of role stores. I am assuming that the default ones should work. Is there something special that I need to do in the Startup.cs
to get the roles working? I'm using mvc 6 beta 2 default template.
回答1:
The User.IsInRole()
does not work if I add a role like this:
await UserManager.AddToRoleAsync(user, "Admin");
But it does work if I do this:
await UserManager.AddClaimAsync(user, claim: new Claim(ClaimTypes.Role.ToString(), "Admin"));
回答2:
It looks like you're using Asp.NET Identity with the latest ASP.NET 5 stuff. I'm using the same (currently using RC1). I had a similar issue, and after some digging I found a solution by using SignInManager
's RefreshSignInAsync()
method.
Note that to get a hold of an instance of UserManager
and SignInManager
I use dependency injection, so the constructor for my controller looks like this:
public MyController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
My requirement was that if a particular controller method was accessed by an authenticated user, then a role would be added to that user if the user didn't already have that role, and it needed to take effect immediately. (Subsequent calls to User.IsInRole("TheRole")
in controllers and views need return true without the user having to log out and back in).
Here's the action:
[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");
}
}
Note you need
using System.Security.Claims;
for the GetUserId()
extension method.
So the big things that I learned was to use UserManager
's AddToRoleAsync
and SignInManager
's RefreshSignInAsync
. The first adds a row to the AspNetUserRoles table. The second refreshes the cookie that, with the next request from the browser, will show that the user is in the role.
As an aside, I added a method called EnsureRoles()
to Startup.cs. I call it right after the call to app.UseIdentity()
in Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
. So, here's a snipit from 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
...
and here is 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));
}
}
}
}
}
来源:https://stackoverflow.com/questions/28356740/how-to-turn-on-roles-in-asp-net-identity-3-0-and-mvc-6