C# User.IsInRole在ASP.NET核心中不返回任何内容(实现了存储库模式)
我有一个ASP.NET核心(完整的.NET Framework)应用程序,配置如下: Startup.csC# User.IsInRole在ASP.NET核心中不返回任何内容(实现了存储库模式),c#,asp.net-core,asp.net-identity,C#,Asp.net Core,Asp.net Identity,我有一个ASP.NET核心(完整的.NET Framework)应用程序,配置如下: Startup.cs public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configu
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>(p => {
p.Password.RequireDigit = true;
p.Password.RequireNonAlphanumeric = false;
p.Password.RequireUppercase = true;
p.Password.RequiredLength = 5;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddTransient<IDbFactory, DbFactory>();
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<IUserService, UserService>();
}
public void配置服务(IServiceCollection服务)
{
//添加框架服务。
services.AddDbContext
用户表
用户角色表
在我的登录操作中,我有以下内容:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
if (User.IsInRole("Admin"))
{
return RedirectToAction("Index", "Home", new { area = "Admin" });
}
return RedirectToAction("Index", "Home");
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction("ObeyMyOrder");
}
}
public async Task<IActionResult> ObeyMyOrder()
{
if (User.IsInRole("Admin"))
{
return RedirectToAction("Index", "Home", new { area = "Admin" });
}
return RedirectToAction("Index", "Home");
}
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
公共异步任务登录(LoginViewModel模型,字符串returnUrl=null)
{
ViewData[“ReturnUrl”]=ReturnUrl;
if(ModelState.IsValid)
{
//这不会将登录失败计入帐户锁定
//要启用密码故障触发帐户锁定,请设置lockoutOnFailure:true
var result=wait _signInManager.PasswordSignInAsync(model.Username、model.Password、model.RememberMe、lockoutOnFailure:false);
if(result.successed)
{
if(User.IsInRole(“Admin”))
{
返回RedirectToAction(“Index”,“Home”,new{area=“Admin”});
}
返回重定向到操作(“索引”、“主页”);
}
if(结果要求系数)
{
return RedirectToAction(nameof(SendCode),new{ReturnUrl=ReturnUrl,RememberMe=model.RememberMe});
}
如果(结果IsLockedOut)
{
_logger.LogWarning(2,“用户帐户锁定”);
返回视图(“锁定”);
}
其他的
{
AddModelError(string.Empty,“登录尝试无效”);
返回视图(模型);
}
}
//如果我们走到这一步,有些东西失败了,重新显示形式
返回视图(模型);
}
我想要实现的是在登录后将用户重定向到某个区域
我目前面临的问题是,函数User.IsInRole(“Admin”)
返回false,并且在调试模式下,如果我查看usermanager,当前用户没有加载角色(Count=0)
如有任何想法,将不胜感激
更新1
忽略角色Id原因是错误的。事实上,用户已使用正确的值映射。用户。IsInRole
正在检查cookie。但您正在登录时的同一http请求中检查此项。cookie根本还不存在-它将在答复或下一个请求时可用
此时,您需要使用ApplicationUserManager.IsInRoleAsync(TKey userId,string role)
来检查数据库。经过数小时的搜索,我在使用Azure Active Directory和角色时意识到了这一点
User.HasClaim(ClaimTypes.Role,"admin");
这并不重要
User.IsInRole("admin");
我还发现了与Kaptain Babbalas相同的问题,并发现在OnTokenValidated中手动重新添加角色会使User.Claims的结果加倍,但会导致User.IsInRole正常工作
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = (context) =>
{
var claims = new List<Claim>();
foreach (var claim in context.Principal.Claims)
{
if (claim.Type == ClaimTypes.Role) claims.Add(new Claim(ClaimTypes.Role, claim.Value));
}
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
context.Principal.AddIdentity(claimsIdentity);
return Task.CompletedTask;
}
};
options.Events=新建OpenIdConnectEvents
{
OnTokenValidated=(上下文)=>
{
var索赔=新列表();
foreach(context.Principal.Claims中的var索赔)
{
if(claim.Type==ClaimTypes.Role)claims.Add(新的claim(ClaimTypes.Role,claim.Value));
}
var claimsIdentity=新的claimsIdentity(索赔、CookieAuthenticationDefaults.AuthenticationScheme);
上下文、主体、附加性(索赔性);
返回Task.CompletedTask;
}
};
如果有人(像我一样)在.Net Core 2.1中为此而挣扎
简而言之,如果您像这样使用AddDefaultIdentity
:
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDefaultIdentity()
.AddEntityFrameworkStores();
那么角色将无法工作,因为它们没有在DefaultIdentity中实现
对我有效的方法是将其替换为:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddIdentity()
.AddRoleManager()
.AddEntityFrameworkStores()
.AddDefaultUI()
.AddDefaultTokenProviders();
另外,如果您在上述修复之前登录,请注销并再次登录,以便刷新身份声明。现在它应该可以工作。User.IsInRole()
在SignIn
之后处理下一个请求。SignIn
和User.IsInRole()在您的代码中
正在同一请求中执行。因此,要应用手动重定向,您可以将身份验证代码放入另一个操作中,并从登录()重定向到该操作,如下所示:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
if (User.IsInRole("Admin"))
{
return RedirectToAction("Index", "Home", new { area = "Admin" });
}
return RedirectToAction("Index", "Home");
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction("ObeyMyOrder");
}
}
public async Task<IActionResult> ObeyMyOrder()
{
if (User.IsInRole("Admin"))
{
return RedirectToAction("Index", "Home", new { area = "Admin" });
}
return RedirectToAction("Index", "Home");
}
public异步任务登录(LoginViewModel模型,字符串returnUrl=null)
{
ViewData[“ReturnUrl”]=ReturnUrl;
if(ModelState.IsValid)
{
//这不会将登录失败计入帐户锁定
//要启用密码故障触发帐户锁定,请设置lockoutOnFailure:true
var result=wait _signInManager.PasswordSignInAsync(model.Username、model.Password、model.RememberMe、lockoutOnFailure:false);
if(result.successed)
{
返回重定向到操作(“服从myorder”);
}
}
公共异步任务服从myOrder()
{
if(User.IsInRole(“Admin”))
{
返回RedirectToAction(“Index”,“Home”,new{area=“Admin”});
}
返回重定向到操作(“索引”、“主页”);
}
现在,User.IsInRole()
可以工作了。从.Net Core 2.1开始(也可以在3.1中工作),AddDefaultIdentity
与调用:
附加属性
AddDefaultUI
AddDefaultTokenProviders
要添加角色功能,请转到ConfigureServices
下的Startup.cs
,您可以像这样使用.AddRoles
:
services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>() //<-- This line
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDefaultIdentity()
.AddRoles()//在我的例子中,当用户已经登录时,我已将该用户添加到数据库中的角色中。注销并重新登录解决了此问题。登录操作中如何可能存在用户
?回答得很好。谢谢。我已经