有效地检查角色声明

Efficiently check role claim

我正在开发 Asp.NET MVC5 Web 应用程序 (.NET 4.6),我需要向具有特定声明的一组用户显示一些额外的 HTML 行。我见过一些冗长的解决方案,但我更喜欢保持简短,所以我想到了这个

@{
    if (System.Security.Claims.ClaimsPrincipal.Current.Claims.ToList().FirstOrDefault(c => c.Type == "role" && c.Value == "AwesomeUserRole") != null) {
        <!-- my HTML goes here -->
    }
 }

这是检查经过身份验证的用户声明的好方法还是有最佳实践可供遵循?也欢迎任何更清洁/更高效的解决方案。

因为 ASP.NET 中的所有 Identity 对象现在都是 ClaimsIdentity,你总是可以将当前的 IPrincipal 转换为 ClaimsIdentity:

((System.Security.Claims.ClaimsIdentity)User.Identity).HasClaim("role", "AwesomeUserRole")

但实际上只使用 User.IsInRole("AwesomeUserRole")

最简单

只要您没有更改默认配置,role 类型的声明就会自动输入到线程主体的角色集合中。

如果您需要检查角色以外的其他声明类型,我通常会为 IPrincipal 创建一组扩展方法来包装声明检查:

public static bool CanDoX(this IPrincipal principal)
{
    return ((ClaimsIdentity)principal.Identity).HasClaim(claimType, claimValue);
}

扩展方法的好处是您可以检查任何类型的声明和 return 它们可能包含的任何值,而不仅仅是声明是否存在。

请记住,委托人可以有多个身份与之关联,例如您已经使用 Windows 身份验证进行了身份验证,但随后添加了一个带有来自您数据库的声明的自定义身份。

因此任何索赔检查都可能需要查看所有身份,这里有一些扩展方法可以提供帮助

public static bool ClaimExists(this IPrincipal principal, string claimType)
{
    var ci = principal as ClaimsPrincipal;
    if (ci == null)
    {
        return false;
    }

    var claim = ci.Claims.FirstOrDefault(x => x.Type == claimType);

    return claim != null;
}

public static bool HasClaim(this IPrincipal principal, string claimType,
                            string claimValue, string issuer = null)
{
    var ci = principal as ClaimsPrincipal;
    if (ci == null)
    {
        return false;
    }

    var claim = ci.Claims.FirstOrDefault(x => x.Type == claimType
                                         && x.Value == claimValue
                                         && (issuer == null || x.Issuer == issuer));

    return claim != null;
}