Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# User.IsInRole在ASP.NET核心中不返回任何内容(实现了存储库模式)_C#_Asp.net Core_Asp.net Identity - Fatal编程技术网

C# User.IsInRole在ASP.NET核心中不返回任何内容(实现了存储库模式)

C# 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

我有一个ASP.NET核心(完整的.NET Framework)应用程序,配置如下:

Startup.cs

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()//在我的例子中,当用户已经登录时,我已将该用户添加到数据库中的角色中。注销并重新登录解决了此问题。

登录操作中如何可能存在
用户
?回答得很好。谢谢。我已经