你是对的
-
JSON 中 BOM 字符不合法(并且不需要)
-
JSON 中的 MIME 字符集不合法(也不需要)
RFC 7159,第 8.1 节:
实现不得将字节顺序标记添加到 JSON 文本的开头。
这是尽可能清楚地说明的。这是整个 RFC 中唯一“不得”的内容。
RFC 7159,第 11 节:
JSON 文本的 MIME 媒体类型是 application/json。
类型名称:应用程序
子类型名称:json
所需参数:不适用
可选参数:不适用
[...]
Note: 没有为此注册定义“字符集”参数。
JSON编码
JSON 唯一有效的编码是 UTF-8、UTF-16 或 UTF-32,并且由于第一个字符(如果有多个字符,则为前两个字符)的 Unicode 值始终低于 128(没有有效的 JSON可以包含前两个字符的较高值的文本)只需查看字节流,总是可以知道使用了哪种有效编码以及哪种字节序。
RFC推荐
JSON RFC 规定前两个字符始终低于 128,您应该检查前 4 个字节。
我会以不同的方式表达:由于字符串“1”也是有效的 JSON,因此无法保证您有两个字符 - 更不用说 4 个字节了。
我的推荐
我对确定 JSON 编码的建议会略有不同:
快速方法:
- 如果你有 1 个字节并且它不是 NULL - 它是UTF-8
(实际上这里唯一有效的字符是 ASCII 数字)
- 如果你有 2 个字节并且没有一个是 NUL - 它是UTF-8
(这些必须是没有前导“0”的 ASCII 数字,{}
, []
or ""
)
- 如果你有 2 个字节并且只有第一个是 NUL - 它是UTF-16BE
(它必须是编码为 UTF-16、大端的 ASCII 数字)
- 如果你有 2 个字节并且只有第二个是 NUL - 它是UTF-16LE
(它必须是编码为 UTF-16、小端的 ASCII 数字)
- 如果你咬了 3 口并且它们不为 NULL - 这是UTF-8
(同样,没有前导 '0' 的 ASCII 数字,"x"
, [1]
etc.)
- 如果您有 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 中包含的验证稍微严格一些的验证来验证您是否具有:
- UTF-8、UTF-16 或 UTF-32(LE 或 BE)的有效编码
- 有效的 JSON
仅查找 NUL 字节是不够的。
话虽如此,在任何时候,您都不需要任何 BOM 字符来确定编码,也不需要 MIME 字符集- 两者都不需要并且在 JSON 中无效.
使用 UTF-16 和 UTF-32 时只需使用二进制内容传输编码,因为它们可能包含 NUL 字节。 UTF-8 没有这个问题,并且 8 位内容传输编码很好,因为它在字符串中不包含 NUL(尽管它仍然包含 >= 128 的字节,因此 7 位传输将不起作用 - 有 UTF- 7 可以用于此类传输,但它不是有效的 JSON,因为它不是唯一有效的 JSON 编码之一)。
也可以看看这个答案更多细节。
回答您的后续问题
这些扣除是否正确?
Yes.
在实施遵循此解释的 Web 服务或 Web 客户端时,我会遇到问题吗?
如果您与不正确的实现进行交互,则可能会出现这种情况。为了与不正确的实现进行互操作,您的实现可能会忽略 BOM - 请参阅RFC 7159,第 1.8 节:
为了互操作性,实施
解析 JSON 文本可能会忽略字节顺序标记的存在
而不是将其视为错误。
此外,忽略 MIME 字符集是兼容 JSON 实现的预期行为 - 请参阅RFC 7159,第 11 节:
注意:没有为此注册定义“charset”参数。
添加一项实际上对合规收件人没有任何影响。
安全考虑
我个人并不认为总是需要默默地接受不正确的 JSON 流。如果您决定接受带有 BOM 和/或 MIME 字符集的输入,那么您将必须回答这些问题:
- 如果 MIME 字符集与实际编码不匹配怎么办?
- 如果 BOM 和 MIME 字符集不匹配怎么办?
- 如果 BOM 与实际编码不匹配怎么办?
- 当它们全部不同时该怎么办?
- 如何处理 UTF-8/16/32 以外的编码?
- 您确定所有安全检查都会按预期进行吗?
将编码定义在三个独立的位置 - JSON 字符串本身、BOM 和 MIME 字符集中,这使得问题不可避免:如果他们不同意该怎么办。除非你拒绝这样的输入,否则就没有明显的答案。
例如,如果您有一个代码验证 JSON 字符串,以查看在 JavaScript 中对其进行评估是否安全 - 它可能会被 MIME 字符集或 BOM 误导,并将其视为与实际不同的编码,而不检测字符串它会检测是否使用了正确的编码。 (HTML 的类似问题过去曾导致 XSS 攻击。)
每当您决定接受具有多个且可能冲突的编码指示符的不正确 JSON 字符串时,您就必须为所有这些可能性做好准备。这并不是说您永远不应该这样做,因为您可能需要使用由不正确的实现生成的输入。我只是说你需要彻底考虑其中的含义。
不合格的实施
我是否应该针对违反上述两个属性的网络浏览器提交错误?
当然 - 如果他们称之为 JSON 并且实现不符合 JSON RFC,那么它就是一个错误,应该如此报告。
您是否发现任何不符合 JSON 规范的特定实现,但他们却宣传这样做?