JSON规范和BOM / charset编码的使用

时间:2011-02-14 08:27:11

标签: json mime-types rfc

我一直在阅读RFC-4627规范,我来解释一下:

将有效负载宣传为application/json mime-type时,

  1. 必须在正确编码的JSON流的开头没有BOM(基于“3.编码”部分)和
  2. 不支持媒体参数,因此application/json; charset=utf-8的mime类型标头符合RFC-4627(基于“6. IANA注意事项”部分)。< / LI>

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

2 个答案:

答案 0 :(得分:19)

你是对的

  1. 物料清单字符在JSON中是非法的(并且不需要)
  2. MIME字符集在JSON中是非法的(也不需要)
  3. RFC 7159, Section 8.1

      

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

    尽可能清楚地说明这一点。这是唯一的&#34; MUST NOT&#34;在整个RFC中。

    RFC 7159, Section 11

      

    JSON文本的MIME媒体类型是application / json   输入名称:申请
      子类型名称:json
      所需参数:n / a
      可选参数:n / a
      [...]
      注意: No&#34; charset&#34;参数是为此注册定义的。

    JSON编码

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

    RFC建议

    JSON RFC说前两个字符总是低于128,你应该检查前4个字节。

    我会换一种说法:因为字符串&#34; 1&#34;也是有效的JSON,不能保证你有两个字符 - 更不用说4个字节。

    我的推荐

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

    快速方法:

    1. 如果您有1个字节并且它不是NUL - 它的 UTF-8
      (实际上这里唯一有效的字符是ASCII数字)
    2. 如果您有2个字节但没有一个是NUL - 它的 UTF-8
      (那些必须是ASCII数字,没有前导&#39; 0&#39;,{}[]""
    3. 如果您有2个字节且只有第一个是NUL - 它的 UTF-16BE
      (它必须是编码为UTF-16,大端的ASCII数字)
    4. 如果您有2个字节且只有第二个是NUL - 它的 UTF-16LE
      (它必须是编码为UTF-16的ASCII数字,小端)
    5. 如果您有3个字节而且它们不是NUL - 它 UTF-8
      (再次,没有前导&#39; 0&#39;,"x"[1]等的ASCII数字。)
    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
    7. 但只有当它确实是任何这些编码中的有效字符串时才有效,但它可能不是。此外,即使您在5种有效编码之一中有一个有效字符串,它仍然可能不是有效的JSON。

      我的建议是使用比RFC中包含的更严格的验证来验证您的验证:

      1. UTF-8,UTF-16或UTF-32(LE或BE)的有效编码
      2. 有效的JSON
      3. 只查看NUL字节是不够的。

        有人说过,在任何时候你都不需要有任何BOM字符来确定编码,你也不需要MIME字符集 - 两者都不需要,而且在JSON中无效

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

        有关详细信息,另请参阅this answer

        回答您的后续问题

          

        这些是否正确扣除?

          

        在实施符合此解释的网络服务或网络客户端时,我会遇到问题吗?

        可能,如果您与不正确的实现进行交互。为了与不正确的实现进行互操作,您的实现可能会忽略BOM - 请参阅RFC 7159, Section 1.8

          

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

        此外,忽略MIME字符集是符合JSON实现的预期行为 - 请参阅RFC 7159, Section 11

          

        注意:没有&#34; charset&#34;参数是为此注册定义的。   添加一个对合规收件人没有任何影响。

        安全注意事项

        我个人并不认为总是需要默默地接受不正确的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那么它就是一个bug,应该这样报告。

        您是否发现任何不符合JSON规范的具体实施,但他们做广告是为了这样做?

答案 1 :(得分:2)

我认为你对问题1是正确的,因为第3节关于前两个字符是ASCII和unicode FAQ on BOMs,请参阅“问:我应该如何处理BOM?”,回答第3部分。强调 MUST 可能有点强烈:常见问题解答似乎意味着应该

不知道问题2的答案。