首页 > 解决方案 > 使用内置身份服务器在 asp net core 3.0 中添加和访问声明

问题描述

我目前无法解决索赔问题。我有一个 ASP.Net Core 3 项目,其中有角度模板和存储在应用程序中的用户。

我想向我的用户添加声明,阅读我认为这很容易,只需添加一些类似的内容

await _UserManager.AddClaimAsync(user, new Claim(AccountStatic.ClaimTypes._Claim_Id, user.Id));

当您创建用户时,然后在他们再次登录后使用以下行将其取回:

User.FindFirst(AccountStatic.ClaimTypes._Claim_Id)?.Value;

然而,这不起作用。我可以看到声明被写入AspNetUserClaims我的数据库中的表中,但用户登录时声明中不存在声明。那里还有一些其他声明,但不是我添加的声明。

我是否需要在某个地方定义哪些用户声明在登录时包含在内?

编辑。 我发现一个帖子说我需要使用 DI AddClaimsPrincipalFactory 添加声明。所以我添加了这个类。

public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
    public UserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager,IOptions<IdentityOptions> optionsAccessor): base(userManager, optionsAccessor)
    {}

    //https://levelup.gitconnected.com/add-extra-user-claims-in-asp-net-core-web-applications-1f28c98c9ec6
    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var identity = await base.GenerateClaimsAsync(user);
        identity.AddClaim(new Claim(AccountStatic.ClaimTypes.Claim_Id, user.Id ?? "[no id]"));
        return identity;
    }
}

如果我单步执行代码,我可以看到这里添加的声明。但是在控制器中,我的自定义声明不存在。

internal string GetUserId()
{
    if (User.Identity.IsAuthenticated == false)
        return null;

    return User.FindFirst(AccountStatic.ClaimTypes.Claim_Id)?.Value;
}

更新。好的,我觉得这很奇怪。我一直在尝试做其他人声称的工作,但对我来说,没有什么能让我得到用户名或 ID。检查User我得到以下信息。这里没有任何内容包含对登录用户的任何引用。

在此处输入图像描述

更新2: 刚刚注意到那里实际上有一个ID:{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: ed107a11-6c62-496b-901e-ed9e6497662a}似乎是数据库中的用户ID。不知道如何访问它。

这些返回 null。

User.FindFirst(JwtRegisteredClaimNames.NameId)?.Value;
User.FindFirst("nameidentifier")?.Value;
User.FindFirst("NameIdentifier")?.Value;

我正在使用另一个更新UserClaimsPrincipalFactory并对其进行断点并查看声明,我可以看到我想要的所有内容都在那里。但同样,这些在我的 API 控制器中不可用,如第一张图片所示。 在此处输入图像描述

标签: asp.net-coreidentityserver4.net-core-3.0

解决方案


我终于明白了这个问题,这在很大程度上要归功于 Ruard van Elburgs 的评论,以及他在链接问题IdentityServer4 Role Based Authorization中的回答。

问题是声明没有添加到访问令牌中。有两个令牌,访问令牌和身份令牌。- Ruard van Elburg

他们了解正在发生的事情的关键是发现有两个令牌,并且它们包含不同的声明并具有不同的目的。

如果您认为有必要,您可以强制将一个令牌的声明也包含在另一个令牌中。

我的问题的解决方案是将其添加到 Startup.ConfigureServices

services
    .AddIdentityServer(options => {})
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
    {
        foreach (var c in options.ApiResources)
        {
            // the string name of the token I want to include
            c.UserClaims.Add(AccountStatic.ClaimTypes.Claim_Id); 
        }
    });

我还没有想出如何获取身份令牌,但是由于我现在将用户 ID 包含在访问令牌中,所以我的问题暂时得到了解决。


推荐阅读