2.1. HTTP Fields (HTTP 字段)
2.1. HTTP Fields (HTTP 字段)
HTTP 字段的组成部分名称是其字段名的小写形式, 如 [HTTP] 第 5.1 节所定义. 虽然 HTTP 字段名不区分大小写, 实现将它们用作组成部分名称时必须使用小写字段名 (例如 content-type, date, etag).
HTTP 字段的组成部分值是按 [HTTP] 第 5.5 节所定义该命名字段的字段值. 除非下文附加参数与规则 (如 req 与 tr 标志) 覆盖, 字段值必须从目标消息的命名字段头字段取得. 对大多数字段, 字段值如 [HTTP] 所建议为 ASCII 字符串, 组成部分值即该字符串. 某些实现可能存在其他编码, 所有非 ASCII 字段值在加入签名基之前必须编码为 ASCII. 第 2.1.3 节所述 bs 参数提供包装此类问题字段值的方法.
除非附加参数与规则覆盖, HTTP 字段值必须按 [HTTP] 第 5.2 节合并为单一值以创建组成部分值. 具体地, 作为多个字段发送的 HTTP 字段必须使用单个逗号与单个空格 ("," + " ") 作为分隔符连接各值. 注意中间人允许以逗号间任意空白合并 HTTP 字段值, 若验证者未考虑此行为, 签名可能失败, 因为签名者与验证者各自签名基中的组成部分值会不同. 为稳健性, 建议签名消息对签名下覆盖的任意字段仅包含单个实例, 特别对使用下述算法序列化的基于列表的字段值. 该方法增加字段值经中间人保持未触碰的可能性. 若无法做到且需分别发送某字段的多个实例, 建议签名者与验证者处理任何基于列表的字段时取所有单独字段值并按下述严格算法合并, 以对抗可能的中间人行为. 当问题字段为 List 或 Dictionary 类型的 Structured Field 时, 可通过要求字段值的严格 Structured Field 序列化 (第 2.1.1 节) 更直接地达到此效果.
注意某些 HTTP 字段 (如 Set-Cookie [COOKIE]) 的语法不允许以这种方式合并字段值 (使得合并输出从多个输入无歧义). 尽管组成部分值从不被消息签名过程解析, 仅作为签名基 (第 2.5 节) 的一部分使用, 将此类字段纳入签名时仍需谨慎, 因为合并值可能产生歧义. 第 2.1.3 节所述 bs 参数提供包装此类问题字段的方法. 关于此问题的更多讨论见第 7.5.6 节.
若实现对某字段无法直接取得正确合并值, 下列算法将为基于列表的字段产生规范化结果:
-
按各实例在消息中出现 (或将出现) 的顺序, 创建该字段每个实例的字段值的有序列表.
-
去除列表中每一项的前导与尾随空白. 注意由于合规实现中 HTTP 字段值不允许包含前导与尾随空白, 此步在合规实现中应为空操作.
-
移除行内任何过时的行折叠 (obs-fold), 并以单个空格 (" ") 替换, 如 [HTTP/1.1] 第 5.2 节所述. 注意该行为专属于 HTTP/1.1, 不适用于不允许内部行折叠的其他 HTTP 规范版本.
-
在各项之间以单个逗号 (",") 与单个空格 (" ") 连接值列表.
所得字符串即为该字段的组成部分值.
注意某些 HTTP 字段的值存在多种有效序列化但语义等价, 例如允许不区分大小写的值而中间人可能改变大小写. 签名并处理此类字段的应用必须考虑如何处理这些字段的值, 以确保签名者与验证者能推导出相同值, 如第 7.5.2 节所述.
下列为在给定示例 HTTP 消息片段下, 头字段组成部分值的非规范性示例:
Host: www.example.com Date: Tue, 20 Apr 2021 02:07:56 GMT X-OWS-Header: Leading and trailing whitespace. X-Obs-Fold-Header: Obsolete line folding. Cache-Control: max-age=60 Cache-Control: must-revalidate Example-Dict: a=1, b=2;x=1;y=2, c=(a b c)
下列示例以上述头字段的组成部分值展示, 使用第 2.5 节定义的签名基格式:
"host": www.example.com "date": Tue, 20 Apr 2021 02:07:56 GMT "x-ows-header": Leading and trailing whitespace. "x-obs-fold-header": Obsolete line folding. "cache-control": max-age=60, must-revalidate "example-dict": a=1, b=2;x=1;y=2, c=(a b c)
消息中存在时也可对空 HTTP 字段签名. 规范化值为空字符串. 这意味着下列空头字段 (以 (SP) 表示空字段值前单个尾随空格):
X-Empty-Header:(SP)
由签名基生成算法 (第 2.5 节) 序列化时, 在组成部分标识符后的冒号与空格之后跟随空字符串值.
"x-empty-header":(SP)
任意 HTTP 字段组成部分标识符在特定情形下可具有下列参数, 各参数在其专节详述:
sf 布尔标志, 指示组成部分值使用 Structured Field 值的严格编码序列化 (第 2.1.1 节).
key String 参数, 用于从 Dictionary Structured Field 中选择单个成员值 (第 2.1.2 节).
bs 布尔标志, 指示各字段值在合并为组成部分值之前使用 Byte Sequence 数据结构编码 (第 2.1.3 节).
req 用于已签名响应的布尔标志, 指示组成部分值派生自触发此响应消息的请求, 而非直接来自响应消息. 注意该参数也可应用于针对请求的任意派生组成部分标识符 (第 2.4 节).
tr 布尔标志, 指示字段值按 [HTTP] 第 6.5 节定义取自消息的 trailer. 若缺少该标志, 字段值按 [HTTP] 第 6.3 节定义取自消息的 header 字段 (第 2.1.4 节).
可同时指定多个参数, 尽管某些组合冗余或不兼容. 例如, 在 Dictionary 项上使用 key 参数时 sf 的功能已被覆盖, 因为 key 要求值的严格序列化. bs 参数要求来自消息的字段值原始字节, 与要求解析后数据结构的 sf 或 key 参数不兼容.
附加参数可在第 6.5 节建立的 "HTTP Signature Component Parameters" 注册表中定义.