.Net 6 的 System.IdentityModel.Tokens.Jwt 的自定义对象 JSON 序列化实现是否存在问题?

Is there an issue with the custom object JSON serialization implementation of System.IdentityModel.Tokens.Jwt for .Net 6?

我们从 .Net Core(dotnet 核心)3.1 迁移到 .Net 6。我们使用 System.IdentityModel.Tokens.Jwt 创建有效负载并使用该有效负载生成安全令牌。

我们的应用程序还没有从 Newtonsoft.Json 迁移到 System.Text.Json 因为有很多非标准属性 目前有利于前者的连载。自定义声明值包含一个对象,该对象之前已通过遵守在 Startup.cs 配置中针对 JSON 序列化指定的 camelCase 合同解析器正确序列化。

我们从 System.IdentityModel.Tokens.Jwt 版本 5.5.0 升级到版本 6.16.0 并且序列化行为不同。

我们混合使用了 IdentityModel 知名声明和自定义声明。自定义声明是唯一一个作为对象的声明,也是唯一一个以这种方式表现的声明。所有其他声明都是原始类型,并按照指定和预期写入令牌。

这是无效代码的示例:

 var payload = new JwtPayload()
            {
                {JwtRegisteredClaimNames.Iss, issuer},
                {JwtRegisteredClaimNames.Iat, now},
                {JwtRegisteredClaimNames.Nbf, now},
                {JwtRegisteredClaimNames.Exp, exp},
                {JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")},
                {"role", user.UserType},
                {"customClaim", customClaimObjectInstance }
            };

var jwt = new JwtSecurityToken(_jwtHeader, payload);

/* Token below contains a valid base64 encoded JWT Token with
   the customClaim property containing pascal values that match
   the properties of the C# Poco object and not at all following       
   either default convention or even any JsonProperty description 
   attributes such as [JsonProperty("name")] that may decorate each 
   property of the custom object */
var token = _jwtSecurityTokenHandler.WriteToken(jwt);

我的第一个预感是它可能与 System.Text.Json 的默认库发生冲突。我通过将 [JsonPropertyName("name")] 属性添加到某些属性来继续进行故障排除,但没有成功。我希望如果使用 System.Text.Json,那么在声明对象的序列化过程中至少会尊重或参考那些描述属性。

我还尝试使用 Newtonsoft JsonConverter.Serialize 函数序列化该值,并将序列化后的值用作声明键值对的值。然而,字符串化的对象引号被转义并发现大量转义字符(“****”)遍及不需要的值。

在网上搜索了一段时间并尝试找到合适的关键字来搜索 google 和 GitHub 之后,我终于找到了我目前考虑的解决方法,而不是 long-term解决方案。

Github 上的这个公开 issue 提供了线索。根据我的解释,我只是通过在实例化问题中发布的 payload 变量之前指定以下行来强制使用 Newtonsoft 序列化和反序列化委托:

JsonExtensions.Serializer = JsonConvert.SerializeObject;
JsonExtensions.Deserializer = JsonConvert.DeserializeObject;

这是第一个可能 System.Text.Json 被从图书馆深处强迫的迹象。这也可能表明是时候优先从 Newtonsoft.Json 迁移到 System.Text.Json

我希望这个变通办法能帮助其他人获得这个 short-term 补丁,而不是像我那样花费太多。

如果我发现关于这件事的更多具体想法或线索,我会更新这个答案。

下面的代码有效

    /* This was the key to achieving the prior result, however 
       temporary it may be. */
        JsonExtensions.Serializer = JsonConvert.SerializeObject;
        JsonExtensions.Deserializer = JsonConvert.DeserializeObject;
        
        var payload = new JwtPayload()
        {
            {JwtRegisteredClaimNames.Iss, issuer},
            {JwtRegisteredClaimNames.Iat, now},
            {JwtRegisteredClaimNames.Nbf, now},
            {JwtRegisteredClaimNames.Exp, exp},
            {JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")},
            {"role", user.UserType},
            { "customClaim", customClaimObjectInstance}
       };

       var jwt = new JwtSecurityToken(_jwtHeader, payload);
       var token = _jwtSecurityTokenHandler.WriteToken(jwt);

感谢 github 上的问题,但更重要的是感谢 here.

提出的解决方案