为什么JWT被分成三个点分隔的部分?

为什么JWT被分成三个点分隔的部分?,jwt,Jwt,JSON Web令牌(JWT)分为三个Base-64编码的部分,由句点(“.”)连接。前两部分对JSON对象进行编码,第一部分是详述签名和哈希算法的头,第二部分包含断言。第三种是二进制数据,即签名本身 我的问题是:为什么JSON Web令牌被分成这样三个独立的部分?似乎将它们编码为单个JSON对象会使解析它们变得更容易,就像这样(为了简洁起见,下面的示例不完整): 另一种说法是:为什么JWT的设计者不把JWT的所有部分都放在一个JSON对象中,如上图所示?虽然我不是为设计JWT的人说话,但我能想

JSON Web令牌(JWT)分为三个Base-64编码的部分,由句点(“.”)连接。前两部分对JSON对象进行编码,第一部分是详述签名和哈希算法的头,第二部分包含断言。第三种是二进制数据,即签名本身

我的问题是:为什么JSON Web令牌被分成这样三个独立的部分?似乎将它们编码为单个JSON对象会使解析它们变得更容易,就像这样(为了简洁起见,下面的示例不完整):


另一种说法是:为什么JWT的设计者不把JWT的所有部分都放在一个JSON对象中,如上图所示?

虽然我不是为设计JWT的人说话,但我能想到你的建议不会成功的一个主要原因:

标题不允许换行 请记住,JWT的主要用例是将其用作cookie值。Cookie在标题中被传递。标题值不支持换行:每个标题键/值对需要适合一行

因此,对于在HTTP请求中作为头值传递的内容,任意JSON将不起作用

因此,需要某种编码——这就是为什么首先使用base64。base64经常出现的原因是,它将任何blob或字符串转换为几乎在任何情况下都可以作为简单ascii可靠传输的内容。也就是说,三个用句点分隔的base64编码的“有效载荷”(在base64编码中不是有效字符)几乎可以保证在几乎任何系统之间安全地传输而不会损坏

JSON不能做出同样的保证。当然,您可以删除换行符(JSON无论如何都会忽略空格),但引号仍然是一个问题:它们应该在URL中编码,在其他情况下可能不会,尽管它们可能在HTTP头中也可以。结果,当开发人员第一次尝试实现它时,它又变成了一个“陷阱”


我相信还有其他原因:这不是一个全面的列表。

我相信,这会带来更多问题。是的,您可以很好地解析它,但是签名的验证呢

JWT的结构是
。签名基本上是前两部分签名。结构不太可能被各种框架以任何方式修改

现在考虑JSON:在序列化和反序列化过程中,元素的顺序可能会变长。对象
{a:1,“b:2}
{b:2,“a:1}
在javascript中可能相等,但如果将它们字符串化,它们将生成不同的签名

此外,要检查签名,您需要确定用于生成签名的标准JSON格式(例如,美化或缩小)。同样,不同的选择将生成不同的签名


因此,简单使用JSON带来的麻烦多于好处签名不能作为签名的一部分,因此必须单独使用

标头和有效负载可以组合到JSON对象上,但这将是一个糟糕的设计。JWT库的工作是检查头并验证签名。这可以(也应该)在不考虑有效载荷的情况下完成。应用程序的任务是对有效负载做出反应。只要签名签出,就可以不必担心头


独立的消费者,独立的对象。

整个令牌可能很大,将它们切碎可以避免在每个可能的处理步骤中解析整个令牌。最好询问程序员,这可能属于Stackoverflow。因为所有的数据都在那里,构建令牌只是一个简单的连接问题,所以这个决定并不是基于任何与安全相关的理由。@conorman第三段是错误的(现在神秘地丢失了)。我认为设计问题仍然存在,不仅仅是命名。@conormance要验证数据的完整性,您需要从JSON负载中重新创建“令牌”。若你们的序列化库改变了JSON对象中元素的顺序,那个么即使并没有人弄乱数据,你们的签名也是无效的。
{
    "header": {
        "alg": "rsa"
    },
    "assertions": {
        "iss": "2019-10-09T12:34:56Z"
    },
    "sig": "qoewrhgoqiethgio3n5h325ijh3=="
}