【问题标题】:How to make custom user claims be available in API requests如何使自定义用户声明在 API 请求中可用
【发布时间】:2018-12-10 16:28:01
【问题描述】:

我的解决方案包括:

  • 在 ASP.NET Identity Core 之上运行 IdentityServer4 的 ASP.NET Core 2.1。
  • ASP.NET Core 2.1 Web API 设置为使用 IdentityServer 作为身份验证提供程序。
  • 使用 oidc-client javascript 库的 React SPA Web 应用程序。

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

然后,在我的 API 项目中,我想在控制器内部获取经过身份验证的用户的用户声明。
我原以为 this.User.Claims 会为我提供这些,但它返回的是以下内容,这似乎是与客户端应用程序相关的声明,而不是与用户相关的声明。

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

【问题讨论】:

  • 您是否在使用访问令牌?如果是这样,您可以将用户声明编码到令牌中,这应该隐式允许您通过this.User.Claims 访问它们。如果失败,您将需要创建访问 UserManager 的方法。
  • 是的,我正在使用访问令牌(通过 Authorization: Bearer xxxx 标头)。不确定如何将声明编码到 IdentityServer 中的令牌中。任何解释如何做到这一点的帖子/资源?

标签: c# asp.net identityserver4 claims-based-identity asp.net-identity-3


【解决方案1】:

因此,在 IdentityServer 启动时设置 ApiResource 时,我要求我的自定义用户声明在每个 API 请求中可用。

//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) 来获取它。

【讨论】:

  • 谢谢!!这个我找了好久!
【解决方案2】:

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

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

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

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

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

【讨论】:

  • 我无法让它工作,但我找到了一个更简单的解决方案。不知道为什么没有人指出这一点。看我的回答。
【解决方案3】:

我为 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;
}

【讨论】:

  • 这只是一个辅助方法。 ClaimsPrincipal.Claims 中没有我要查找的声明。
【解决方案4】:

您可以使用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

【讨论】:

  • 这不起作用。问题不在于如何访问它们,问题在于访问令牌中不存在声明。 IdentityServer4 端应该有一些东西告诉它在令牌中包含这些声明。
  • 我明白了。这是一个简单的示例:korzh.com/blogs/net-tricks/….
猜你喜欢
  • 2014-12-23
  • 2020-01-30
  • 2023-03-15
  • 2017-03-23
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多