【问题标题】:User.IsInRole() returns false and Authorize Roles gives me an Access DeniedUser.IsInRole() 返回 false 并且 Authorize Roles 给了我拒绝访问
【发布时间】:2018-12-11 16:28:07
【问题描述】:

我正在尝试使用 ASP.NET Core Identity 2.0 在我现有的应用程序中设置身份验证。当我使用自己的数据库架构和类时,我有自己的用户和角色类,我必须创建自定义 UserStore/UserManager/RoleStore/RoleManager。

我在我的服务中声明它们:

services.AddIdentity<User, Profile().AddUserManager<CustomUserManager<User>>().AddRoleManager<CustomRoleManager>().AddDefaultTokenProviders();
services.AddTransient<IUserStore<User>, UserStore>();
services.AddTransient<IRoleStore<Profile>, ProfileStore>();
services.AddTransient<UserResolverService>();

我用这些方法在 UserStore 中实现了 UserRoleStore 接口:

    public Task AddToRoleAsync(User user, string roleName, CancellationToken cancellationToken)
    {
        user.Profiles.Add(db.Profiles.ToList().Find(x => x.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase)));

        db.SaveChanges();

        return Task.FromResult((object)null);
    }

    public Task RemoveFromRoleAsync(User user, string roleName, CancellationToken cancellationToken)
    {
        user.Profiles.Remove(db.Profiles.ToList().Find(x => x.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase)));

        db.SaveChanges();

        return Task.FromResult((object)null);
    }

    public Task<IList<string>> GetRolesAsync(User user, CancellationToken cancellationToken)
    {
        IList<string> ret = new List<string>();
        user.Profiles.ToList().ForEach(x => ret.Add(x.Name));
        return Task.FromResult(ret);
    }

    public Task<bool> IsInRoleAsync(Useruser, string roleName, CancellationToken cancellationToken)
    {
        Profile searchRole = db.Profiles.Include(profile => profile.ProfileUsers).ToList().Find(x => x.Active && x.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase));
        return Task.FromResult(searchRole.ProfileUsers.ToList().Find(x => x.UserID == user.ID) == null ? false : true);
    }

    public Task<bool> IsInRole(User user, string roleName, CancellationToken cancellationToken)
    {
        return Task.FromResult(true);
    }

    public Task<IList<Utilisateur>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken)
    {
        Profile currentProfile = db.Profiles.Include(profile => profile.ProfileUsers).ThenInclude(pu => pu.User).ToList().Find(x => x.Active && x.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase));
        if (currentProfile == null)
        {
            return Task.FromResult((IList<User>)null);
        }

        IList<User> ret = new List<User>();
        currentProfile.ProfileUsers.ToList().ForEach(x => ret.Add(x.User));
        return Task.FromResult(ret);
    }

所以当我尝试做的时候

var result1 = _userManager.AddToRoleAsync(userObject, "WorkOrderViewer");
var res = _userManager.GetUsersInRoleAsync("WorkOrderViewer");
var test = await _userManager.IsInRoleAsync(userObject, "WorkOrderViewer");

它有效,我的用户获得了选择的角色。但是,当我尝试在视图中设置控制器授权或控件可见性时,它不起作用。例如,对于控制器授权,我拒绝访问。

当我把它放在我的代码中时:

var test = User.IsInRole("WorkOrderViewer");

即使我登录应用程序(我尝试注销并登录)并且如果 UserManager.IsInRoleAsync 返回“true”,它也会返回“false”。

我认为它失败了,因为 UserManager.AddToRoleAsync() 与 User.IsInRole() 不同步,但我不知道如何解决它。 你知道我做错了什么吗?

【问题讨论】:

    标签: c# asp.net-core asp.net-identity asp.net-core-identity


    【解决方案1】:

    当您说您使用代码 User.IsInRole 时,我假设您的意思是 Controller。

    控制器中的User 是ClaimsPrincipal 类型。

    并且ClaimsPrincipal.IsInRole方法有以下文档:

    IsInRole 方法检查此声明主体拥有的身份是否包含类型为 ClaimsIdentity.RoleClaimType 的声明,其中声明的值等于角色参数指定的值。

    这可以通过查看source for ClaimsIdentity.cs 来确认。

    if (_identities[i].HasClaim(_identities[i].RoleClaimType, role))
    

    所以User.IsInRole正在检查用户是否有 RoleClaimType 类型的声明(默认为“http://schemas.microsoft.com/ws/2008/06/identity/claims/role”)。

    可以根据需要配置声明类型。

    【讨论】:

    • 不错!这是我需要的。如何配置声明类型?我认为你必须创建一个实现 IPrincipal 的类,你在哪里声明它?在服务配置中?
    猜你喜欢
    • 2019-03-06
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 2019-12-20
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多