JwtToken -声明名称JwtTokenTypes.主题解析为ClaimTypes.NameIdentifier,为

本文关键字:ClaimTypes NameIdentifier 声明 JwtTokenTypes JwtToken | 更新日期: 2023-09-27 18:03:50

我已经创建了JwtToken:

        X509Certificate2 cert = certificateStore.Certificate;
        var now = DateTime.UtcNow;
        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenDescriptor = new SecurityTokenDescriptor()
        {
            Subject = new ClaimsIdentity(new[]
            {
                    new Claim(JwtClaimTypes.Subject, upn),
                    new Claim(REQUEST_TYPE_NAME, requestType),
                    new Claim(DOMAIN_NAME, domain),
                }),
            Lifetime = new Lifetime(now, now.AddMinutes(60)),
            SigningCredentials = new X509SigningCredentials(cert),
            TokenIssuerName = ISSUER
        };
        SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);

这是正确的。创建令牌,它的第一个声明名为"sub",它是jwttokenttypes . subject的内容。我通过jwt web检查过了。

问题是,我有这个方法来解决索赔:

        if (string.IsNullOrWhiteSpace(token)) throw new MissingTokenException("Token should not be null.");
        var tokenHandler = new JwtSecurityTokenHandler();
        var securityToken = new X509SecurityToken(new X509Certificate2(new X509RawDataKeyIdentifierClause(certificateStore.Certificate).GetX509RawData()));
        var validationParameters = new TokenValidationParameters()
        {
            IssuerSigningToken = securityToken,
            ValidateAudience = false,
            ValidateActor = false,
            ValidIssuer = ISSUER
        };
        SecurityToken securedToken = new JwtSecurityToken();
        ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out securedToken);
        Claim claim = claimsPrincipal.FindFirst(m => string.Equals(m.Type, REQUEST_TYPE_NAME, StringComparison.OrdinalIgnoreCase));
        if (claim != null && !string.Equals(claim.Value, requestType, StringComparison.OrdinalIgnoreCase))
        {
            throw new MismatchedTokenException("Token is not of the proper type.");
        }
        upn = claimsPrincipal.Claims.FirstOrDefault(m => m.Type.Equals(JwtClaimTypes.Subject) || m.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
        domain = claimsPrincipal.Claims.FirstOrDefault(m => m.Type.Equals(DOMAIN_NAME))?.Value;

在方法的最后,您可以看到我为JwtClaimTypes检查索赔名称。Subject(它应该是)和ClaimTypes。nameidentiview,它实际上是。

你知道为什么会发生这种转换或者如何防止它们吗?

JwtToken -声明名称JwtTokenTypes.主题解析为ClaimTypes.NameIdentifier,为

您需要在前面添加:

JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();

清除jwt的声明映射。

进行映射是为了使jwt声明适应。net类型的声明。如果要从Identity (IPrincipal)中使用名称和角色的声明类型,则需要避免映射。IsInRole或Identity.Name).

您可以在创建ClaimsIdentity时这样做:

    Subject = new ClaimsIdentity(new[]
    {
            new Claim(JwtClaimTypes.Subject, upn),
            new Claim(REQUEST_TYPE_NAME, requestType),
            new Claim(DOMAIN_NAME, domain),
        }, "<auth type>", "name", "role"),

你必须将authType更改为cookie之类的东西,而名称和角色声明名称很可能就是这样的。

另一种方法是在令牌验证参数上设置它:
var validationParameters = new TokenValidationParameters()
    {
        IssuerSigningToken = securityToken,
        ValidateAudience = false,
        ValidateActor = false,
        ValidIssuer = ISSUER,
        NameClaimType = "name",
        RoleClaimType = "role"
    };