为啥 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值

Posted

技术标签:

【中文标题】为啥 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值?【英文标题】:Why does UserAuthExtensions.PopulateFromMap(session, jwtPayload) does not deserialize json values with escape correctly in ServiceStack.Auth?为什么 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值? 【发布时间】:2021-12-19 08:02:54 【问题描述】:

我们想从 ServiceStack 会话中获取 UserName,但是我们发现 UserName 中的反斜杠没有按预期反序列化。用户名的格式为“域名\用户名”,并在 jwt 令牌中序列化,如下所示:


  "typ": "JWT",
  "alg": "HS256"
.
  "iss": "ssjwt",
  "iat": 1635952233,
  "exp": 1635955833,
  "name": "Robin Doe",
  "preferred_username": "domainname\\robindoe"
.[Signature]

调用后:

var sessionFromJwt = JwtAuthProviderReader.CreateSessionFromJwt(req);
userName = sessionFromJwt.UserName;

userName 变量包含值 'domainname\\robindoe' 而不是 'domainname\robindoe'

在挖掘 ServiceStack 代码后,我们将其归结为 https://github.com/ServiceStack/ServiceStack/blob/36df74a8b1ba7bf06f85262c1155e1425c082906/src/ServiceStack/Auth/UserAuth.cs#L388 中的 PopulateFromMap() 方法。

为了演示这个问题,我们编写了一个小程序来证明这一点:

    class Program
        
            static void Main(string[] args)
            
                var jwtPayload = JsonObject.Parse(@"
      ""iss"": ""ssjwt"",
      ""iat"": 1635952233,
      ""exp"": 1635955833,
      ""name"": ""John Doe"",
      ""preferred_username"": ""domainname\\username""
    ");
    
                var session = new AuthUserSession();
    
                // The PopulateFromMap implementation does not deserialize the json values according to json standards
                 UserAuthExtensions.PopulateFromMap(session, jwtPayload);
    
                // Notice that the session.UserName still has the escape character 'domainname\\username' instead of the expected 'domainname\username'
                Console.WriteLine(session.UserName);
    
                // The PopulateFromMap should deserialize also the values, like in test Can_dynamically_parse_JSON_with_escape_chars()
                Can_dynamically_parse_JSON_with_escape_chars();
            
    
            private const string JsonCentroid = @"""place"": ""woeid"":12345, ""placeTypeName"":""St\\a\/te""  ";
    
// Source: https://github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/JsonObjectTests.cs
            public static void Can_dynamically_parse_JSON_with_escape_chars()
            
                var placeTypeName = JsonObject.Parse(JsonCentroid).Object("place").Get("placeTypeName");
                if (placeTypeName != "St\\a/te")
                    throw new InvalidCastException(placeTypeName + " != St\\a/te");
    
                placeTypeName = JsonObject.Parse(JsonCentroid).Object("place").Get<string>("placeTypeName");
                if (placeTypeName != "St\\a/te")
                    throw new InvalidCastException(placeTypeName + " != St\\a/te");
            
    
        

为什么 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值?

【问题讨论】:

【参考方案1】:

问题是由于枚举 JsonObject 没有返回与索引它相同的转义字符串值,这已从 this commit 解决。

此更改从 v5.12.1+ 开始可用,现在是 available on MyGet。

【讨论】:

感谢您的快速回复!我们现在使用的是 ServiceStack 5.4,并计划更新到最新版本。在我的示例中,您的新解决方案非常完美!同时,我们使用以下代码转义该值:JsonTypeSerializer.Instance.UnescapeString(session.UserName)

以上是关于为啥 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?