如何使自定义用户声明在 API 请求中可用

How to make custom user claims be available in API requests

我的解决方案包括:

当我创建新用户时,我设置了一些保存在 AspNetUserClaims table 中的自定义声明,如下所示:

然后,在我的 API 项目中,在一个控制器内,我想获得经过身份验证的用户的那些用户声明。
我原以为 this.User.Claims 会给我这些,但结果却返回了以下内容,这似乎是与客户端应用程序相关的声明,而不是与用户相关的声明。

如何从 Web API 项目中的控制器访问这些自定义用户声明 (address, location, tenant_role)?
请记住,API 项目无权访问 UserManager class 或任何 ASP.NET Identity Core 相关的内容。

您可以使用 ClaimsPrincipal.FindFirst() 访问您的自定义声明。

文档: https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.findfirst?view=netcore-2.1

示例:User.FindFirst("your_claim_key").Value

我编写这个扩展器是为了在 MVC 5 中使用,但由于它使用了 http 上下文和系统安全(而不是用户管理器或身份),我假设它的内部结构将在 MVC6 上运行

public static bool UserHasSpecificClaim(this HtmlHelper h, string claimType, string claimValue)
{
    // get user claims
    var user = HttpContext.Current.User as System.Security.Claims.ClaimsPrincipal;

    if (user != null)
    {
        // Get the specific claim if any
        return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
    }

    return false;
}

您需要像这样定义身份资源和范围:

http://docs.identityserver.io/en/latest/topics/resources.html

然后确保它们由您的身份服务器中的 IProfileService 或 IClaimsService 实现公开:

http://docs.identityserver.io/en/latest/reference/profileservice.html

他们的声明可以自己包含在令牌中,也可以根据需要通过用户信息端点访问 - 如果您的声明数据特别大(即在 1000 个字符中),这是明智的。

因此,我命令我的自定义用户声明在每个 API 请求中可用 我在 IdentityServer 启动时设置 ApiResource 时必须执行以下操作。

//Config.cs
public static IEnumerable<ApiResource> GetApiResources()
{
    ApiResource apiResource = new ApiResource("api1", "DG Analytics Portal API")
    {
        UserClaims =
        {
            JwtClaimTypes.Name,
            JwtClaimTypes.Email,
            AnalyticsConstants.TenantRoleClaim // my custom claim key/name
        }
    };

    return new List<ApiResource>
    {
        apiResource
    };
}

此方法传递给 services.AddInMemoryApiResources(或您正在使用的任何存储方法)

IIdentityServerBuilder builder = services
                .AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                })
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources()) // here
                .AddInMemoryClients(Config.GetClients())
                .AddAspNetIdentity<ApplicationUser>();

使用该设置,每当命中 API 端点时,我的自定义 TenantRole 声明就会出现,因此我只需 User.FindFirst(AnalyticsConstants.TenantRoleClaim) 即可获得它。