在 JSON 对象中存储和发送原始文件数据

Storing and sending raw file data within a JSON object

我正在寻找一种方法来传输任何文件类型的原始文件数据和任何可能的内容(我的意思是文件和文件内容都是用户生成的)两种方式都使用 xhr/ajax在 Backbone 前端调用 Django 后端。


编辑:也许问题还不清楚...

如果您在 IDE(例如 Sublime)中打开一个文件,您可以查看和编辑包含该文件的实际代码。我正在尝试将 THAT 原始内容放入 JSON 以便我可以发送到浏览器,它可以被修改,然后发回。

我发布这个问题是因为我的印象是因为这些文件的内容可以有效地使用任何编码语言,只需将内容字符串化并发送似乎 像一个脆弱的解决方案,很容易被破坏或利用。内容可以包含任意数量的 '"{} 字符,这些字符似乎会破坏 JSON 格式,并且转义这些字符会在其中留下工件有效破解它们的代码(不是吗?)。

如果这个假设是错误的,那也是一个可以接受的答案(只要你能指出我忽略的是什么)。


我正在处理的项目是基于浏览器的 IDE,它将从服务器接收完整的文件结构。用户可以 add/remove 文件,编辑这些文件的内容,然后将他们的更改保存回服务器。 sending/receiving 都必须通过 ajax/xhr 调用来处理。

需要 Underscore/jQuery 的解决方案很好,如果有可用的专门管理原始文件数据的东西,我可以引入额外的库。

AFAI 我担心一个简单的 Base64 转换就可以做到。字符串化,转换为 base64,然后将其传递给服务器并在那里解码。然后你将不会有原始文件传输,你仍然会保持你的代码简单。

我知道这个解决方案可能看起来有点太简单了,但想想看:只要有合适的硬件,许多密码算法都可以破解。最安全的方法之一是通过数字证书,然后使用私钥加密数据,然后将其发送到服务器。但是,要达到这种安全级别,您的应用程序的每个用户都必须拥有数字证书,我认为这对您的用户来说是一个过高的要求。

所以问问自己,如果实施真正安全的解决方案会给您的用户带来很多麻烦,那么您为什么还需要安全传输?基于此,我重申我之前所说的话。一个简单的 Base64 转换就可以了。您还可以使用其他一些算法,例如 SHA256 或其他算法,以使其更安全。

如果这里唯一关心的是代码文件的原始内容("data" 您的模型正在存储),当存储在 JSON 中时会导致某种类型的问题,这很容易转义您的数据。

将原始代码文件内容字符串化可能会导致问题,因为任何类似于 JavaScript 或 JSON 的内容都会被解析为实际的 JSON 对象。 您的代码文件数据可以而且应该简单地存储为转义字符串。您在这里担心的是,所述字符串可能包含可能破坏存储在 JavaScript 字符串中的字符,这可以通过转义整个字符串来缓解,因此可以转义双重、三重、四重等。转义代码文件中已经转义的任何内容。

本质上,重要的是记住,文件中的原始代码在存储在数据库中时只不过是经过美化的字符串,除非您动态添加内联元数据.它只是文本,进行标准转义将使以任何格式作为字符串(在 "" 或 '' 内)存储在 JSON.

中是安全的

我建议阅读这个 SO 答案,因为我也引用了它来验证我认为正确的内容: How To Escape a JSON string containing newline characters using JavaScript

有趣的问题。实现这个所需的代码会非常复杂,抱歉我没有提供示例,但你看起来像一个不错的程序员,应该能够实现下面提到的内容。

关于通过 JSON 发送原始数据,要使其 JSON 安全且不破坏您的代码,您需要做的就是使用 [= 通过 stringyfying 转义特殊字符127=] 的 json.dumps & JavaScript 的 JSON.stringyfy。 [1]

如果您担心某种形式的基本防篡改,那么除了让客户端和服务器通过每个-会话令牌与 JSON 来回传输以确保 JSON 不是从恶意地址伪造的。

如果您想检查数据的端到端完整性,则生成一个 md5 校验和并将其发送到您的 JSON 中,然后生成另一个到达时的 md5 并与 JSON.

中的进行比较

Base64 编码:您的数据大小将增加 33%,因为它编码四个字符来表示三个字节的数据。

Base85:将四个字节编码为五个字符,并将您的数据增加 25%,但比 Python 中的 Base64 使用更多的处理开销。这是数据大小的 8% 改进,但以处理开销为代价。此外,它不是字符串安全的,因为双引号和单引号、尖括号和符号不能在 JSON 中使用,因为它使用所有 95 个可打印的 ASCII 字符。需要在 JSON 传输之前进行字符串化。 [2]

yEnc 仅有 2-3% 的开销(取决于数据中相同字节的频率),但被不切实际的缺陷排除(参见 [3] ).

ZeroMQ Base-85,又名 Z85。它是 Base85 的字符串安全变体,数据开销为 25%,优于 Base64。无需将其粘贴到 JSON 中。我强烈推荐这种编码算法。 [4] [5] [6]

如果您只发送小文件(比如几 KB),那么二进制到文本转换的开销是可以接受的。对于大到几 Mb 的文件,让它们增长 25-33% 可能是不可接受的。在这种情况下,您可以尝试在发送前压缩它们。 [7]

您也可以使用 multipart/form-data 将数据发送到服务器,但我看不出这将如何双向工作。

更新

总之,这是我的解决方案的算法:

发送数据

  • 生成会话令牌并为关联用户存储它 登录(服务器),或从会话 cookie 中检索(客户端)

  • 为数据生成 MD5 散列,以便在传输过程中进行完整性检查。

  • 使用 Z85 对原始数据进行编码以添加一些基本的防篡改和JSON-友好性。

  • 将上面的内容放在 JSON 中,并在请求时发送 POST。

接待处

  • 从POST

  • 抓取JSON
  • 从关联用户(服务器)的存储中检索会话令牌,或从会话 cookie(客户端)中检索。

  • 为接收到的数据生成 MD5 散列,并根据接收到的 MD5 进行测试 JSON,有条件地拒绝或接受。

  • Z85-解码收到的数据JSON得到原始数据并存储在文件或数据库(服务器)或process/display在GUI/IDE(客户端)根据需要。


参考资料

[1] How to escape special characters in building a JSON string?

[2]Binary Data in JSON String. Something better than Base64

[3] https://en.wikipedia.org/wiki/YEnc

[4]http://rfc.zeromq.org/spec:32

[5] C/C++ https://github.com/artemkin/z85

中的 Z85 实现

[6] Z85 Python 执行 https://gist.github.com/minrk/6357188

[7] JavaScript 压缩库 http://stuk.github.io/jszip/

[8] JavaScript Gzip 所以 JavaScript implementation of Gzip