User.IsInRole在ASP.NET Core中没有返回任何内容(已实现存储库模式)

Cri*_*jak 8 c# asp.net-identity asp.net-core

我有一个ASP.NET Core(完整.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>();
}
Run Code Online (Sandbox Code Playgroud)

ApplicationUser从IdentityUser扩展而ApplicationDbContext扩展了IdentityDbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base()
    {
    }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public virtual void Commit()
    {
        base.SaveChanges();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder builder)
    {
        base.OnConfiguring(builder);

        builder.UseSqlServer("connection string here");
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);

        // Configure model
        // Identity
        new Configuration.Identity.ApplicationUserConfiguration(builder.Entity<ApplicationUser>());
        new Configuration.Identity.ApplicationUserProfileConfiguration(builder.Entity<ApplicationUserProfile>());
        new Configuration.Identity.RoleConfiguration(builder.Entity<IdentityRole>());
        new Configuration.Identity.RoleClaimConfiguration(builder.Entity<IdentityRoleClaim<string>>());
        new Configuration.Identity.ApplicationUserRoleConfiguration(builder.Entity<IdentityUserRole<string>>());
        new Configuration.Identity.ApplicationUserClaimConfiguration(builder.Entity<IdentityUserClaim<string>>());
        new Configuration.Identity.ApplicationUserLoginConfiguration(builder.Entity<IdentityUserLogin<string>>());
        new Configuration.Identity.ApplicationUserTokenConfiguration(builder.Entity<IdentityUserToken<string>>());
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的演示数据:

角色表

角色表

用户表

用户表

UserRole表

UserRole表

在我的登录操作中,我有以下内容:

[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);
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是在登录后将用户重定向到某个区域.

我面临的当前问题是该函数User.IsInRole("Admin")返回false并且在调试模式下,如果我查看usermanager,则当前用户没有加载角色(Count = 0).

任何想法将不胜感激.

更新1

忽略角色ID原因是错误的.事实上,用户使用正确的值进行映射.

tra*_*max 17

User.IsInRole正在检查cookie.但是您在登录时在同一个http请求中检查此内容.Cookie根本就不存在 - 它将在回复或下一个请求中提供.

此时,您需要使用ApplicationUserManager.IsInRoleAsync(TKey userId, string role)来检查数据库.


Pio*_*rek 9

如果有人(如我)在.Net Core 2.1中为此苦苦挣扎,则此链接可能会有所帮助

简而言之,如果您使用的AddDefaultIdentity是这样的:

services.AddDefaultIdentity<ApplicationUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
Run Code Online (Sandbox Code Playgroud)

然后,角色将无法使用,因为它们没有在DefaultIdentity中实现。

对我有用的是将其替换为:

services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddRoleManager<RoleManager<IdentityRole>>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI()
            .AddDefaultTokenProviders();
Run Code Online (Sandbox Code Playgroud)

另外,如果您在上述修复之前登录,请注销并再次登录,以便刷新身份声明。现在应该可以了。

  • 几天来,我一直在努力解决这个问题,尝试我读过的所有内容。你的帖子为我解决了它。 (2认同)

Kap*_*las 7

经过几个小时的搜索,我在使用Azure Active Directory和Roles时意识到了ASP.Net Core的这项工作

  User.HasClaim(ClaimTypes.Role,"admin");
Run Code Online (Sandbox Code Playgroud)

这不

  User.IsInRole("admin");
Run Code Online (Sandbox Code Playgroud)


Sum*_*one 5

从 .Net Core 2.1 开始(也适用于 3.1),AddDefaultIdentity与调用相同:

  • AddIdentity
  • AddDefaultUI
  • AddDefaultTokenProviders

要添加角色功能,请转到您可以使用的Startup.cs下面,如下所示:ConfigureServices.AddRoles

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()            //<-- This line
    .AddEntityFrameworkStores<ApplicationDbContext>();
Run Code Online (Sandbox Code Playgroud)

这就是所需要的一切。正如上面提到的,注销并重新登录至关重要。

为了记录(并且只是为了测试),我尝试了services.AddIdentity

IServiceCollection 不包含“AddIdentity”的定义...

并且services.AddIdentityCore(在调试并显示页面之前没有错误):

InvalidOperationException:未指定authenticationScheme,并且未找到DefaultChallengeScheme。可以使用 AddAuthentication(string defaultScheme) 或 AddAuthentication(Action configureOptions) 设置默认方案。

您可能可以做更多的事情来让后两者正常工作,但我发布的代码AddDefaultIdentity是我所需要的,以便让User.IsInRole其他角色功能在 .NET Core 2.1 和迄今为止的 3.1 中工作。