如何使自定义用户声明在 API 请求中可用
How to make custom user claims be available in API requests
我的解决方案包括:
- ASP.NET Core 2.1 运行 IdentityServer4 在 ASP.NET Identity Core 之上。
- ASP.NET Core 2.1 Web API 设置为使用 IdentityServer 作为身份验证提供程序。
- 使用
oidc-client
javascript 库的 React SPA Web 应用程序。
当我创建新用户时,我设置了一些保存在 AspNetUserClaims
table 中的自定义声明,如下所示:
然后,在我的 API 项目中,在一个控制器内,我想获得经过身份验证的用户的那些用户声明。
我原以为 this.User.Claims
会给我这些,但结果却返回了以下内容,这似乎是与客户端应用程序相关的声明,而不是与用户相关的声明。
如何从 Web API 项目中的控制器访问这些自定义用户声明 (address, location, tenant_role
)?
请记住,API 项目无权访问 UserManager
class 或任何 ASP.NET Identity Core
相关的内容。
您可以使用 ClaimsPrincipal.FindFirst()
访问您的自定义声明。
示例: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)
即可获得它。
我的解决方案包括:
- ASP.NET Core 2.1 运行 IdentityServer4 在 ASP.NET Identity Core 之上。
- ASP.NET Core 2.1 Web API 设置为使用 IdentityServer 作为身份验证提供程序。
- 使用
oidc-client
javascript 库的 React SPA Web 应用程序。
当我创建新用户时,我设置了一些保存在 AspNetUserClaims
table 中的自定义声明,如下所示:
然后,在我的 API 项目中,在一个控制器内,我想获得经过身份验证的用户的那些用户声明。
我原以为 this.User.Claims
会给我这些,但结果却返回了以下内容,这似乎是与客户端应用程序相关的声明,而不是与用户相关的声明。
如何从 Web API 项目中的控制器访问这些自定义用户声明 (address, location, tenant_role
)?
请记住,API 项目无权访问 UserManager
class 或任何 ASP.NET Identity Core
相关的内容。
您可以使用 ClaimsPrincipal.FindFirst()
访问您的自定义声明。
示例: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)
即可获得它。