【问题标题】:Proper way to assess Role in Authorization as User.IsInRole() always returns false作为 User.IsInRole() 评估授权角色的正确方法总是返回 false
【发布时间】:2018-10-27 11:31:06
【问题描述】:

关于 User.IsInRole 的问题很多,但我找不到正确的答案。

我需要使用 AuthorizationHandler(通过授权要求)验证某个角色

我有一个 ASP.NET Core 2.1 项目,其中包含个人用户帐户。我已经为数据库播种并使用userManager.AddToRoleAsync 将用户添加到(一个角色)角色,是的,数据库显示了用户、角色和他们之间的连接。

我创建了一个 CandidateViewHandler 来控制 View-Contorller 的授权。它看起来如下

public class CandidateViewHandler : AuthorizationHandler<ViewCandidateRequirement, Candidate>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ViewCandidateRequirement requirement, Candidate resource)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            if (resource.Email == context.User.FindFirst(ClaimTypes.Name).Value)
            {
                context.Succeed(requirement);
            }
            else
            {
                bool IsAdmin = context.User.IsInRole("Administrator");
                bool IsSearch = context.User.IsInRole("Searcher");                    
                if (IsAdmin == true || IsSearch == true)
                {
                    context.Succeed(requirement);
                }
            }
        }
        return Task.CompletedTask;
    }
}

但是,IsAdminIsSearch 总是返回 false。即使在控制器中对其进行测试,结果也保持不变。我应该在 2.1 中使用 Claims 吗?如果有,怎么做?

【问题讨论】:

    标签: asp.net-mvc asp.net-core asp.net-identity claims-based-identity


    【解决方案1】:

    IMO 的 Charles de M. 提到的讨论实际上表明,角色实际上是身份的不必要添加。在我看来,将来最好删除 AspNetRoles 表(或至少不再使用它)并直接使用角色作为声明,而不是通过身份将角色添加为声明.

    将您的角色类型声明添加到 AspNetUserClaims 表中。默认role claim typehttp://schemas.microsoft.com/ws/2008/06/identity/claims/role。该类型的任何声明都应自动映射为角色,以便与 IsInRole 一起使用。

    您也可以在客户端使用自定义映射:

    services.AddAuthentication()
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
                {
                    RoleClaimType = "role",
                    NameClaimType = "name",
                };
        });
    

    附带说明,您可以考虑不再使用角色,因为 asp.net 核心有许多更高级的功能可用于授权。

    【讨论】:

    • 您好 Ruard,感谢您的评论。我肯定会尝试一下。我发现“索赔”的概念仍然很混乱,文档甚至更多。假设我的 ApplicationUser 中有一个自定义属性(例如“TenantId”),我可以直接将其作为声明引用,还是应该先将其添加为 ClaimsType?。
    • 简单地说,一个声明就是一个键/值对。您可以将它用于任何属性,甚至角色。只要“key”(声明类型)对其使用是唯一的(允许集合:role=admin,role=manager)。所以添加一个声明tenantid=42 就可以了,但是http://mycompany.com/tenantid 更有特色。 Identity 将自动向用户添加声明,而对于 ApplicationUser 属性,您必须编写代码将这些属性添加为声明。您也可以跳过该步骤并将属性直接添加到索赔表中。作为奖励,您不必再扩展 IdentityUser。
    【解决方案2】:

    显然 ASP.NET CORE 2.1 在处理角色时存在问题:https://github.com/aspnet/Identity/issues/1813,正如该线程中所解释的那样。不过,问题仍然存在于如何用声明替换角色。

    解决方法是回退到 startup 文件中的旧配置:

    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI()
            .AddDefaultTokenProviders()
    

    (所以删除 AddDefaultIdentity&lt;ApplicationUser&gt;.AddRole&lt;ApplicationRole&gt; 并替换为 AddIdentity&lt;AppplicationRole, ApplicationUser&gt;。现在一切正常。

    【讨论】:

    • 我有一个自定义用户,我无法让 IsInRole 执行任何操作,只能返回 true。我有 services.AddIdentity
    • 我需要查看您的代码。在这种情况下,我建议将其作为问题发布,而不是作为评论发布。更多的人——以及更好的程序员——可以帮助你。并查看我包含的链接github.com/aspnet/Identity/issues/1813
    猜你喜欢
    • 2018-01-07
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    • 2021-04-11
    • 2019-01-31
    • 2015-08-02
    相关资源
    最近更新 更多