Asp.net mvc 以用户身份评估授权中角色的正确方法。IsInRole()始终返回false

Asp.net mvc 以用户身份评估授权中角色的正确方法。IsInRole()始终返回false,asp.net-mvc,asp.net-core,asp.net-identity,claims-based-identity,Asp.net Mvc,Asp.net Core,Asp.net Identity,Claims Based Identity,关于User.IsInRole的问题很多,但我找不到正确的答案 我需要使用AuthorizationHandler(通过authorizationrequirement)验证某个角色 我有一个ASP.NET Core 2.1项目,其中包含个人用户帐户。我已使用userManager.AddToRoleAsync为数据库添加种子并将用户添加到(一个角色)角色,是的,数据库显示了用户、角色以及它们之间的连接 我创建了一个CandidateViewHandler,用于控制视图控制器的授权。情况如下 p

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

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

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

我创建了一个CandidateViewHandler,用于控制视图控制器的授权。情况如下

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;
    }
}
公共类CandidateViewHandler:AuthorizationHandler
{
受保护的覆盖任务HandleRequirementAsync(授权HandlerContext上下文、ViewCandidateRequirement需求、候选资源)
{
if(context.User.Identity.IsAuthenticated)
{
if(resource.Email==context.User.FindFirst(ClaimTypes.Name).Value)
{
成功(要求);
}
其他的
{
bool IsAdmin=context.User.IsInRole(“管理员”);
bool-IsSearch=context.User.IsInRole(“搜索者”);
如果(IsAdmin==true | | IsSearch==true)
{
成功(要求);
}
}
}
返回Task.CompletedTask;
}
}

但是,
IsAdmin
IsSearch
始终返回
false
。即使在控制器中进行测试,结果仍然相同。我是否应该在2.1中使用
索赔
?如果是这样的话,怎么办?

很明显,ASP.NET CORE 2.1在处理角色时遇到了问题:,如该线程中所述。然而,问题仍然在于如何用声明取代角色

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

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

(因此,删除
AddDefaultIdentity.AddRole
并替换为
AddIdentity
。现在一切正常。

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

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

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

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

一个旁注,您可以考虑不再使用任何角色,因为ASP.NET核心有许多更高级的功能,您可以用来授权。

Hi-Ruad,谢谢您的评论。我一定会尝试它。我发现“索赔”-概念仍然很混乱,文档更详细。假设我有一个自定义属性(例如,我有一个自定义属性)。“TenantId”)在我的ApplicationUser中,我可以直接引用它作为声明,还是应该首先将其添加为ClaimsType?简单地说,声明是一个键/值对。您可以将其用于任何属性,甚至角色。只要“键”(声明类型)的使用是唯一的(允许集合:role=admin,role=manager).因此可以添加声明
tenantid=42
,但是
http://mycompany.com/tenantid
更独特。Identity将自动向用户添加声明,而对于ApplicationUser属性,您必须编写代码将这些属性添加为声明。您也可以跳过该步骤,直接将属性添加到claims表。作为奖励,您不必再扩展IdentityUser。我有一个自定义用户,我无法让IsInRole执行任何操作,只能返回true。我有服务。AddIdentity我需要查看您的代码。我建议将其作为问题发布,而不是作为注释发布。这样,更多的人——以及更好的程序员——可以帮助您.然后看看我包含的链接。