即使在声明中存在角色,IsInRole也会返回false

时间:2016-01-29 09:31:06

标签: c# asp.net-mvc-5 authorization iis-8.5

我正在处理声明基础身份验证,它运行正常。 现在我想添加角色自动化。 我有用户的角色声明(例如“Admin”)

  

调用IsInRole()方法时,会检查是否存在   当前用户具有该角色。在声明感知应用程序中,角色   由角色声明类型表示,该类型应该在   令牌。角色声明类型使用以下URI表示:   http://schemas.microsoft.com/ws/2008/06/identity/claims/role

//Include all claims
//claims is List<Claim> with all claims
 var id = new ClaimsIdentity(claims, "Cookies");
 Request.GetOwinContext().Authentication.SignIn(id);

如果我检查用户是否在角色中,我会得到错误。虽然我的角色声明带有“管理员”值

User.IsInRole("Admin");

同时授权我的api上的attrubute不起作用

[Authorize (Roles = "Admin")]

我可能误解了如何让角色对用户可见。可能只是将Roles列入索赔列表中呢?

5 个答案:

答案 0 :(得分:11)

如果您的服务使用的是Windows身份验证,则您收到的IPrincipal.Identity类型为WindowsPrincipal。这有点误导,但ClaimType寻找的WindowsPrincipal.IsInRole()不是ClaimTypes.Role,正如您可能合理预期的那样,而是ClaimTypes.GroupSid

但是,您不应该假设当前Identity用于指定角色的实际ClaimType,因为不同类型的标识使用不同的值。相反,您应该引用ClaimsIdentity.RoleClaimType属性。

我们在以下几行中实施了IAuthenticationFilter

public Task AuthenticateAsync(HttpAuthenticationContext context, cancellationToken)
{
    var principal = context.Principal;

    if(principal.Identity is ClaimsIdentity && principal.Identity.IsAuthenticated)
    {
        var ci = (ClaimsIdentity)principal.Identity;
        // get the user's additional roles from somewhere and add Claims
        ci.AddClaim(new Claim(ci.RoleClaimType, "MyRole"));
    }
}

这允许我们在ASP.Net控制器中使用标准的AuthorizeAttribute机制。 e.g。

[Authorize(Roles="MyRole")]
public IHttpActionResult Get()
{
    //authenticated and authorised code here
}

有关进一步说明,请参阅MSDN上的ClaimsIdentity.RoleClaimType

请注意:将用户定义的角色添加到WindowsPrincipal可能会导致问题。似乎.Net Framework 4.5的当前实现(截至2017年4月)在检查角色时有时会抛出异常,期望从Active Directory获得角色的详细信息。有关替代方法,请参阅this question

答案 1 :(得分:3)

可能声明的ClaimType只是“角色”。

您应该使用Microsoft Schema创建声明:

manager.AddClaim(dn1.Id, claim: new Claim(ClaimTypes.Role.ToString(), "ADMINISTRATOR"));

然后User.IsInRole("Admin");[Authorize (Roles = "Admin")]将正常运作。

这是因为Microsoft Identity使用架构:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role

何时进行角色检查。 我建议你检查ASPNETIdentity数据库,以便全面了解如何插入che声明。 我很确定AspNetUserClaims的ClaimType与Microsoft Schema不同。

此致

答案 2 :(得分:2)

TL; DR案例敏感度,也许?

我发现默认使用的检查是......

  [Authorize(Roles = "RoleA,RoleB")] 

......区分大小写。

我在大小写混合的情况下创建了角色,并使用了AspNetCore的Identity Manager,并使用非EF内存实现进行测试。
UserManager.IsInRole(&#34; RoleA&#34;)返回true,但是当通过ClaimsPrincipal检查时,HttpContext.User.IsInRole(&#34; RoleA&#34;)返回false。我将声明转发给文本,并且可以看到有正确的MS模式的角色声明...

    ClaimType:[http://schemas.microsoft.com/ws/2008/06/identity/claims/role], ClaimValue:[ROLEA], Issuer:[TokenServer]
    ClaimType:[http://schemas.microsoft.com/ws/2008/06/identity/claims/role], ClaimValue:[ROLEB], Issuer:[TokenServer]

...但是索赔价值(角色)是大写的 要解决这个问题,我只需将属性更改为...

[Authorize(Roles = "ROLEA,ROLEB")]

......它有效。

因此,如果您在让角色授权在AspNetCore中工作时遇到问题,请尝试阅读声明,并完全匹配声明。您可以通过访问HttpContext.User.Claims对象来阅读声明...

        foreach (var claim in HttpContext.User.Claims)            
            Console.WriteLine($"ClaimType:[{claim.Type}], ClaimValue:[{claim.Value}], Issuer:[{claim.Issuer}]");

当然可能是我以某种方式将角色编码为大写字母,或者某处使用了NormalisedRole,但你可能做了同样的事情......

答案 3 :(得分:0)

您没有提到正在使用哪种身份验证方法,但是,如果您使用的是JWT身份验证,则需要在生成令牌时将角色添加到ClaimsIdentity中,如本博文所述:ASP.NET Core JWT mapping role claims to ClaimsIdentity

答案 4 :(得分:0)

请注意 HttpContext.User.Identity.RoleClaimType: “角色”

可能与 ClaimTypes.Role = “ http://schemas.microsoft.com/ws/2008/06/identity/claims/role”

因此,在生成声明标识时,您可能需要使用“角色”作为键而不是ClaimTypes常量来添加声明。 ClaimsIdentity.IsInRole(String)使用ClaimsIdentity.RoleClaimType定义的声明密钥。

我的工厂代码看起来像这样...

            var identity = await base.GenerateClaimsAsync(user);
            var roles = await UserManager.GetRolesAsync(user);
            foreach (var role in roles)
            {
                identity.AddClaim(new Claim(ClaimTypes.Role, role));
                identity.AddClaim(new Claim("role", role));
            }

            return identity;

第一个添加确实是多余的,但让我觉得我实际上是在添加正确的声明。