在 Http Header 中使用 Json 字符串

Posted

技术标签:

【中文标题】在 Http Header 中使用 Json 字符串【英文标题】:Using Json string in the Http Header 【发布时间】:2012-04-04 12:14:54 【问题描述】:

最近我在使用 http 标头时遇到了一些奇怪的问题 (Adding multiple custom http request headers mystery) 为了避免当时的问题,我将字段放入 json 字符串并将该 json 字符串添加到标头中,而不是将这些字段添加到单独的 http标题。

例如,代替

request.addHeader("UserName", mUserName);
request.addHeader("AuthToken", mAuthorizationToken);
request.addHeader("clientId","android_client");

我创建了一个 json 字符串并将其添加到单个标头中

String jsonStr="\"UserName\":\"myname\",\"AuthToken\":\"123456\",\"clientId\":\"android_client\"";
request.addHeader("JSonStr",jsonStr);

由于我是编写 Rest 和处理 Http 的新手,我不知道我的用法是否正确。我希望能对此有所了解。

一些链接

http://lists.w3.org/Archives/Public/ietf-http-wg/2011OctDec/0133.html

【问题讨论】:

只是好奇:您在请求正文中发送什么,使用头部数据? 它是 HttpGet。我没有在正文中发送任何东西。 将整个主体对象编码为 URL 友好格式,放入查询字符串中。在需要的地方解码和解析。 如果你真的需要在header中,base64encode整个JSON字符串在setHeader之前 我认为这是一个有趣的想法。我假设您在标头中传递身份验证数据。由于身份验证数据可能与您请求的目的/意图无关,而只是序言或一种元数据,所以我认为它很适合标题。 【参考方案1】:

是的,您可以在 HTTP 标头中使用 JSON,但有一些限制。

根据HTTP spec,您必须确保您的标题field-body 仅包含可见的 ASCII 字符、制表符或空格,并且不得包含 CR 或 LF 字符(即换行符、除了通过过时的“折叠空格”)。

由于许多 JSON 编码器(例如 php 中的 json_encode)会将 CR 和 LF 字符编码为“\r”和“\n”,并编码不可见或非 ASCII 字符(例如“é”变为“\u00e9 "),你通常不需要担心这个。

检查文档以了解您的特定编码器或对其进行测试,因为JSON strings 在技术上允许大多数 Unicode 字符。例如,JSON.stringify() 默认情况下不会转义多字节 Unicode。但是,您可以轻松地对其进行修改,例如

var charsToEncode = /[\u007f-\uffff]/g;
function http_header_safe_json(v) 
  return JSON.stringify(v).replace(charsToEncode,
    function(c) 
      return '\\u'+('000'+c.charCodeAt(0).toString(16)).slice(-4);
    
  );

Source

或者,您可以按照@rocketspacer 的建议对 JSON 进行 base64 编码,然后再将其插入标题字段(例如,JWT 是如何做到的)。这使得标头中的 JSON(人类)不可读,但确保它符合规范。


值得注意的是,最初的 ARPA 规范 (RFC 822) 对这个确切的用例有一个特殊的描述,这与后来的规范如 RFC 7230 的精神相呼应:

标头的某些字段主体可以根据 一些系统可能希望解析的内部语法。

此外,RFC 822 和 RFC 7230 明确给出没有长度限制:

HTTP 没有对每个标头字段的长度或整个标头部分的长度设置预定义限制,如第 2.5 节所述。

【讨论】:

您能告诉我,在标头中发送 json 是一种好习惯吗?这两种方法有什么区别?什么时候用哪个? 一般来说,header 值比 JSON 简单得多。例如,可以将 JSON 哈希拆分为多个纯文本标头,或者数组可以只是一个分隔列表。在极少数情况下,我只会在标头中使用 JSON。【参考方案2】:

Base64encode 发送前。就像 JSON Web Token 的做法一样。 这是一个 NodeJs 示例:

const myJsonStr = JSON.stringify(myData);
const headerFriendlyStr = Buffer.from(myJsonStr, 'utf8').toString('base64');
res.addHeader('foo', headerFriendlyStr);

当你需要阅读时解码:

const myBase64Str = req.headers['foo'];
const myJsonStr = Buffer.from(myBase64Str, 'base64').toString('utf8');
const myData = JSON.parse(myJsonStr);

【讨论】:

【参考方案3】:

据我了解,在标头选项中使用 json 字符串并不像在 http GET 中使用 http DELETE 那样滥用,因此甚至有人提议在 http 标头中使用 json。当然,仍然欢迎更深入的见解,并且仍有待给出公认的答案。

【讨论】:

【参考方案4】:

一般来说,您不会在 REST API 的标头中发送数据。如果您需要发送大量数据,最好使用 HTTP POST 并在请求正文中发送数据。但看起来您正试图在标头中传递凭据,某些 REST API 确实使用了这些凭据。这是一个example for passing the credentials in a REST API for a service called SMSIfied,它允许您通过 Internet 发送 SMS 文本消息。此示例使用基本身份验证,这是 REST API 的常用技术。但是您需要将 SSL 与此技术一起使用以确保其安全。 Here is an example 关于如何使用 WCF 和 REST 实现基本身份验证。

【讨论】:

我已经拿到了认证部分。 ***.com/q/9643115/319058我比较感兴趣的是分析我在header中json字符串的使用情况 @WinMyoHtet 根据我的回答;不要在标头中发送数据(JSON 或 XML)。使用 POST 并将数据放入请求的正文中。如果您必须使用 GET 将数据放在 URL 查询字符串中。在设计 REST API 时,您使用 GET 来读取数据(即服务没有状态更改),并使用 POST 来插入或更新数据。 我无法理解标头中没有 XML,因为 XML 非常臃肿但 JSON 不同。它重量轻。 (因此,它在提供的邮件线程存档中提出)我在标题中放入的是用于验证用户的授权令牌。我没有在此处进行任何状态更改。 引用线程中的提案尚未被接受。你说你有身份验证部分,但我见过的安全机制都没有在标题中使用清晰的 JSON。为了更好地讨论 REST 安全性,我会查看这篇文章 ***.com/questions/7551/…。最好使用现有的 HTTP 相关安全标准,例如基本身份验证,它使用标头中的编码字符串作为凭据,使用 TSL 进行传输。 我在这里所做的一切都是通过 https。我相信您已经知道 https 加密,包括标头 ***.com/q/187655/319058

以上是关于在 Http Header 中使用 Json 字符串的主要内容,如果未能解决你的问题,请参考以下文章

JSON数据的HTTP Header应该怎么标记

Http的Header里面包含哪些字段,每个字段有哪些含义?

http协议发送header+body+json及接收解析

如何将 JSON 字符串添加到 HTTP 请求标头?

带有特殊字符的 XML 在 C# 中转换为 Json

JWT 使用介绍