一尘不染

JSON规范和BOM /字符集编码的用法

json

我一直在阅读RFC-4627规范,并开始进行解释:

在将有效载荷宣传为application/json哑剧类型时,

  1. 必须 是没有BOM在正确编码JSON的开始小号流(基于部分“3.编码”),以及
  2. 没有媒体参数也被支持,从而一个的mime类型报头application/json; charset=utf-8 符合RFC-4627(基于部分“6. IANA考虑”)。

这些是正确的推论吗?在实施遵循这种解释的Web服务或Web客户端时,我会遇到问题吗?是否应该针对违反上述两个属性的Web浏览器提交错误?


阅读 375

收藏
2020-07-27

共1个答案

一尘不染

你是对的

  1. BOM字符在JSON中是非法的 (不需要)
  2. MIME字符集在JSON中是非法的 (也不需要)

RFC 7159第8.1节

实现不得在JSON文本的开头添加字节顺序标记。

尽可能清楚地说明这一点。这是整个RFC中唯一的“不得”。

RFC 7159第11节

JSON文本的MIME媒体类型为application / json。
类型名称:application
子类型名称:json
必需参数:不适用
可选参数:不适用
[…]
注意: 此注册未定义“字符集”参数。

JSON编码

JSON的唯一有效编码是UTF-8,UTF-16或UTF-32,并且由于第一个字符(如果有多个字符,则为前两个字符)将始终具有小于128的Unicode值(没有有效的JSON)可以包含前两个字符的较高值的文本),始终可以通过查看字节流来知道使用哪种有效编码以及使用哪种字节序。

RFC建议

JSON RFC表示前两个字符将始终在128以下,并且您应检查前4个字节。

我用不同的说法:由于字符串“ 1”也是有效的JSON,因此不能保证您有两个字符-更不用说4个字节了。

我的建议

我对确定JSON编码的建议会稍有不同:

快速方法:

  1. 如果您有1个字节且不是NUL,则为 UTF-8
    (实际上,这里唯一有效的字符是ASCII数字)

  2. 如果你有2个字节,他们都不是NUL -它的 UTF-8
    (那些必须为ASCII数字,没有领先的“0”, {}[]""

  3. 如果您有2个字节,而只有第一个为NUL,则为 UTF-16BE
    (必须为ASCII数字,编码为UTF-16,大端)

  4. 如果您有2个字节,而第二个字节是NUL,则为 UTF-16LE
    (必须为ASCII数字,编码为UTF-16,小端)

  5. 如果您有3个字节,但它们不是NUL,则为 UTF-8
    (同样,不带前导0的ASCII数字"x"[1]等等)

  6. 如果您有4个字节或更多的字节,而不是RFC方法起作用:

    • 00 00 00 xx -这是UTF-32BE
    • 00 xx 00 xx -这是UTF-16BE
    • xx 00 00 00 -这是UTF-32LE
    • xx 00 xx 00 -这是UTF-16LE
    • xx xx xx xx -这是UTF-8

但只有在这些编码中的任何一个确实是有效字符串(如果不是)时,它才有效。而且,即使您具有5种有效编码之一中的有效字符串,它也可能不是有效的JSON。

我的建议是进行比RFC所包含的验证更严格的验证,以验证您具有:

  1. UTF-8,UTF-16或UTF-32的有效编码(LE或BE)
  2. 有效的JSON

仅寻找NUL字节是不够的。

话虽 这么 说, 您根本不需要任何BOM字符来确定编码,也不需要MIME字符集 - 不需要 这两个 字符 ,并且
在JSON中均无效

使用UTF-16和UTF-32时只需要使用二进制内容传输编码,因为它们可能包含NUL字节。UTF-8没有这个问题,并且8位内容传输编码很好,因为它在字符串中不包含NUL(尽管它仍然包含>
= 128的字节,所以7位传输将不起作用-存在UTF- 7可以用于这种传输,但是它不是有效的JSON,因为它不是唯一有效的JSON编码之一)。

回答您的后续问题

这些是正确的推论吗?

是。

在实施遵循这种解释的Web服务或Web客户端时,我会遇到问题吗?

如果您与错误的实现进行交互,则可能会发生。为了与不正确的实现实现互操作性,您的实现可以忽略BOM-参见RFC
7159第1.8节

为了互操作性,解析JSON文本的实现可以忽略字节顺序标记的存在,而不是将其视为错误。

同样,忽略MIME字符集是兼容JSON实现的预期行为-请参阅RFC
7159,第11节

注意:没有为该注册定义“字符集”参数。确实添加一个对符合条件的收件人没有任何影响。

安全注意事项

我个人并不认为始终需要静默接受不正确的JSON流。如果您决定接受带有BOM和/或MIME字符集的输入,则必须回答以下问题:

  • 如果MIME字符集和实际编码不匹配该怎么办?
  • 如果BOM和MIME字符集不匹配怎么办?
  • 如果BOM与实际编码不匹配怎么办?
  • 当所有人都不相同时该怎么办?
  • 使用UTF-8 / 16/32以外的编码怎么办?
  • 您确定所有安全检查都能按预期进行吗?

在三个独立的位置定义编码-
在JSON字符串本身,BOM和MIME字符集中,这不可避免地产生了问题:如果不同意该怎么办。除非您拒绝这样的输入,否则没有一个明显的答案。

例如,如果您有一个验证JSON字符串的代码,以查看是否可以安全地用JavaScript评估它-
可能会被MIME字符集或BOM误导,并且将其视为与实际不同的编码,并且不会检测到字符串它会检测是否使用了正确的编码。(HTML的类似问题过去也导致XSS攻击。)

每当您决定接受带有多个且可能有冲突的编码指示符的不正确的JSON字符串时,就必须为所有这些可能性做好准备。并不是说您绝对不要这样做,因为您可能需要使用错误的实现所产生的输入。我只是说,您需要彻底考虑其含义。

不合格的实施

是否应该针对违反上述两个属性的Web浏览器提交错误?

当然-如果他们将其称为JSON,并且实现不符合JSON RFC,则这是一个错误,应这样报告。

您是否找到了任何不符合JSON规范的特定实现,但它们却宣传这样做呢?

2020-07-27