JSON 规范以及 BOM/charset-encoding 的使用

2023-12-03

我一直在阅读RFC-4627规范,我得出了解释:

当将有效负载广告为application/json哑剧类型,

  1. there MUST be no BOMs 位于正确编码的 JSON 流的开头(基于“3. 编码”部分),以及
  2. 不支持媒体参数,因此 mime 类型标头为application/json; charset=utf-8 does not符合RFC-4627(基于“6. IANA 注意事项”部分)。

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


你是对的

  1. JSON 中 BOM 字符不合法(并且不需要)
  2. 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. 如果你有 1 个字节并且它不是 NULL - 它是UTF-8
    (实际上这里唯一有效的字符是 ASCII 数字)
  2. 如果你有 2 个字节并且没有一个是 NUL - 它是UTF-8
    (这些必须是没有前导“0”的 ASCII 数字,{}, [] or "")
  3. 如果你有 2 个字节并且只有第一个是 NUL - 它是UTF-16BE
    (它必须是编码为 UTF-16、大端的 ASCII 数字)
  4. 如果你有 2 个字节并且只有第二个是 NUL - 它是UTF-16LE
    (它必须是编码为 UTF-16、小端的 ASCII 数字)
  5. 如果你咬了 3 口并且它们不为 NULL - 这是UTF-8
    (同样,没有前导 '0' 的 ASCII 数字,"x", [1] etc.)
  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 编码之一)。

也可以看看这个答案更多细节。

回答您的后续问题

这些扣除是否正确?

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 规范的特定实现,但他们却宣传这样做?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JSON 规范以及 BOM/charset-encoding 的使用 的相关文章

随机推荐

  • 如何在 tsql contains 函数中搜索 &(与号)?

    我有一个表 T 其中有一个列 C 其中包含包含字符 的文本 但是如果我执行以下查询 它不会返回任何内容 尽管我可能有 10 行 SELECT FROM T WHERE Contains C a b 使用双引号使其成为搜索词 SELECT F
  • 从 Asm 访问 C 中定义的全局变量

    我有一个包含全局变量 foo 的 C 文件 我如何访问foo来自另一个汇编程序 我使用 i586 elf as GNU 汇编器 和 i586 elf gcc gnu 编译器 进行构建 您可以只使用交易品种名称 as将所有未定义的符号视为外部
  • EF Core DB First,以及如何避免模型生成时的构造函数覆盖

    我将不再对 Azure DB 使用 SQL 身份验证 而是使用 Active Directory 托管身份验证 如此处所述article 基本上 我正在做两件主要的事情来使其正常工作 1 在 DBContext 构造函数中注入令牌 publ
  • 在 Azure 上部署 Django 应用程序:即使在部署后也仅显示默认应用程序

    我正在尝试将 Web 应用程序部署到 Azure 我正在遵循这些指示https azure microsoft com en us documentation articles web sites python create deploy
  • 通过类路径执行 java -jar vs 在 jar 文件目录中执行 java -jar

    使用 NetBeans 创建 Java 程序后 将其称为 Addition 然后在文件夹 c Users Ben Doc NetBeansProjects Addition dist 中成功清理并构建可执行 Jar 文件 为什么在执行时 从
  • 使用ajax时如何清除缓存数据?

    我正在使用 Ajax 根据某些 ID 从服务器检索数据 如下所示 以执行自动建议功能 但是 当我提交表单并更新数据库时 自动建议字段假设不应再包含此 ID 的任何内容 但它仍会从缓存中检索数据 有谁知道如何清除缓存并使Ajax发送请求以在每
  • 如何使用 WatiN 检查 PDF 是否在浏览器中成功打开?

    我正在使用 WatiN 库在部署后对网站进行快速冒烟测试 除此之外 我想确保当我单击页面上的特定链接时 会在浏览器中打开 PDF 单击链接很容易 但如何检测 Acrobat Reader 是否已在浏览器窗口中成功打开 我想捕获 404 服务
  • /d2vzeroupper MSVC 编译器优化标志有什么作用?

    是什么 d2vzeroupperMSVC编译器优化标志在做什么 我正在阅读此编译器选项快速参考指南 对于 AMD 的 Epyc CPU https developer amd com wordpress media 2020 04 Comp
  • Android导入库

    在我的项目中 我需要使用外部库 该库包括 class文件 我已使用此库将文件夹添加到我的项目中属性 gt Java 构建路径 gt 库 gt 添加类文件夹 我可以毫无问题地编译项目 但是当我运行它时 我得到failed resolving
  • 使用 websocket 发送私人消息

    我们如何使用 Websockets 和 PHP 实现私人消息系统 客户端到客户端 据我了解 服务器广播消息 所有客户端都可以通过 connection onmessage 事件处理程序接收消息 我想知道是否有一种方法可以将消息仅发送给网络套
  • UWP DatagramSocket 多播

    我设法制作了一个简单的应用程序 可以从多播组发送和接收数据 如果我打开应用程序的 2 个实例 具有相同代码的 2 个不同的 sln 文件 我可以发送和接收数据 问题是 5秒后 如果我从Client001发送消息 只有Client001会收到
  • 什么时候可以将日期时间存储为本地时间而不是 UTC?

    这是一个类似于this one 我真的很想在我的应用程序中将日期时间存储为本地时间而不是 UTC 这被认为是最佳实践 在应用程序中 我发生了许多事件 每个事件都分配给给定的位置 当我向用户显示它们时 我总是想显示local活动时间 IE E
  • 在 ruamel 中往返时按原样保留多行字符串

    假设我有一个像这样的文件 test long This is a sample text across two lines 当我加载文件并将其转储回来而不对文件进行任何更改时 它会将此文档更改为 test long This is a sa
  • Swift TableView 转至新的 ViewController,但索引路径错误(倒数第二个选择)

    我有一个奇怪的问题 我有两个 TableView 一个用于显示项目 另一个用于显示所有团队成员 对于两个 TableView 我都有相同的错误 当用户单击项目 团队成员时 我想显示其详细信息 奇怪的是 当运行应用程序并且我第一次选择项目 团
  • 在 Xcode 的 Foundation 代码示例中遇到“cleanup:”。这是什么?

    所以在即将推出的一些示例代码中核心有声读物我遇到了一个陌生的符号 cleanup 它在调用某些 dispose myStuff 函数之前使用 它前面没有 或 似乎你可以输入任何单词 后跟一个冒号 它就会像注释一样 int main int
  • 将字符串转换为特定的日期时间格式

    我已经在谷歌上搜索了一段时间 但我似乎无法找到解决方案 我认为这很容易 但它花了太长时间 我转向 stackoverflow 我需要将包含日期和时间的字符串转换为 DateTime 变量 我已将字符串格式化为我想要存储的确切格式 但是当我将
  • 任何避免警告 C6386 的方法,而不完全禁用它或代码分析

    默认情况下 Visual Studio 2019 开始将代码分析警告显示为编辑器内的绿色波浪线 这些对于学习 C 编程的学生来说可能非常有用 因为他们可以捕获经典错误 例如通过一个数组访问 不幸的是 误报可能会完全破坏学习体验 我担心我将不
  • 删除 Spark 字符串列的第一个字符

    我想知道正如我在标题中所说 对于以下两种情况 如何删除 Spark 字符串列的第一个字符 val myDF1 Seq 14326 1258634 15626 163262 toDF A val myDF2 Seq a14326 c12586
  • 用于查找未使用的包含标头的工具? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 I know PC Lint可以告诉您有关包含但未使用的标头的信息 有没有其他工具可以做到这一点 最好是在 Linux 上 我们有一个庞大的代码库 在过去 15 年里 大量的功能发生
  • JSON 规范以及 BOM/charset-encoding 的使用

    我一直在阅读RFC 4627规范 我得出了解释 当将有效负载广告为application json哑剧类型 there MUST be no BOMs 位于正确编码的 JSON 流的开头 基于 3 编码 部分 以及 不支持媒体参数 因此 m