跳到主要内容

4. HTTP 中的标识符

Uniform Resource Identifiers (URI) [URI] 在 HTTP 中被广泛用作标识资源 (Section 3.1) 的手段.

4.1. URI 引用

URI 引用用于指定请求目标, 指示重定向以及定义关系.

"URI-reference","absolute-URI","relative-part","authority","port","host","path-abempty","segment" 和 "query" 的定义采用 URI 通用语法. 本文为可包含非空路径组件的协议元素定义了 "absolute-path" 规则.(此规则与 RFC 3986 的 path-abempty 规则略有不同, 后者允许空路径; 也与 path-absolute 规则不同, 后者不允许以 "//" 开头的路径.) 本文还为可包含相对 URI 但不能包含片段组件的协议元素定义了 "partial-URI" 规则.

URI-reference = `<URI-reference, see [URI], Section 4.1>`
absolute-URI = `<absolute-URI, see [URI], Section 4.3>`
relative-part = `<relative-part, see [URI], Section 4.2>`
authority = `<authority, see [URI], Section 3.2>`
uri-host = `<host, see [URI], Section 3.2.2>`
port = `<port, see [URI], Section 3.2.3>`
path-abempty = `<path-abempty, see [URI], Section 3.3>`
segment = `<segment, see [URI], Section 3.3>`
query = `<query, see [URI], Section 3.4>`

absolute-path = 1*( "/" segment )
partial-URI = relative-part [ "?" query ]

HTTP 中每个允许 URI 引用的协议元素, 都会在其 ABNF 产生式中说明该元素允许任意形式的引用 (URI-reference), 仅允许绝对形式的 URI (absolute-URI), 仅允许路径和可选查询组件 (partial-URI), 或上述形式的某种组合. 除非另有说明, URI 引用都相对于目标 URI (Section 7.1) 解析.

推荐所有发送方和接收方至少支持协议元素中长度为 8000 个八位字节的 URI. 注意, 这意味着某些结构和线上表示 (例如 HTTP/1.1 中的请求行) 在某些情况下必然更大.

4.2. HTTP 相关 URI Scheme

IANA 在 ````https://www.iana.org/assignments/uri-schemes/\```` 维护 URI Schemes 注册表 [BCP35].虽然请求可以以任何 URI scheme 为目标, 但以下 scheme 是 HTTP 服务器固有的:

URI Scheme描述章节
http超文本传输协议 (Hypertext Transfer Protocol)4.2.1
https安全超文本传输协议 (Hypertext Transfer Protocol Secure)4.2.2

表 2

注意, 存在 "http" 或 "https" URI 并不意味着被标识的 origin 上总有 HTTP 服务器正在侦听连接. 任何人都可以铸造 URI, 无论服务器是否存在, 也无论该服务器当前是否把该标识符映射到某个资源. 注册名称和 IP 地址的委派性质会创建一个联合命名空间, 不管 HTTP 服务器是否存在.

4.2.1. http URI Scheme

本文定义 "http" URI scheme, 用于在层次化命名空间中铸造标识符; 该命名空间由一个潜在 HTTP 源服务器管理, 该服务器在给定端口上侦听 TCP ([TCP]) 连接.

http-URI = "http" "://" authority path-abempty [ "?" query ]

"http" URI 的源服务器由 authority 组件标识, 该组件包含主机标识符 ([URI], Section 3.2.2) 和可选端口号 ([URI], Section 3.2.3). 如果端口子组件为空或未给出, 则默认使用 TCP port 80 (WWW 服务的保留端口).origin 决定谁有权对以所标识资源为目标的请求作出权威响应, 如 Section 4.3.2 所定义.

发送方不得生成主机标识符为空的 "http" URI. 处理此类 URI 引用的接收方必须将其作为无效引用拒绝.

层次化 path 组件和可选 query 组件标识该源服务器命名空间内的目标资源.

4.2.2. https URI Scheme

本文定义 "https" URI scheme, 用于在层次化命名空间中铸造标识符; 该命名空间由一个潜在源服务器管理, 该服务器在给定端口上侦听 TCP 连接, 并且能够建立已为 HTTP 通信安全保护的 TLS ([TLS13]) 连接. 在此上下文中, "安全保护" 具体表示服务器已被认证为代表所标识 authority 行事, 且与该服务器的所有 HTTP 通信都具有客户端和服务器均可接受的机密性和完整性保护.

https-URI = "https" "://" authority path-abempty [ "?" query ]

"https" URI 的源服务器由 authority 组件标识, 该组件包含主机标识符 ([URI], Section 3.2.2) 和可选端口号 ([URI], Section 3.2.3). 如果端口子组件为空或未给出, 则默认使用 TCP port 443 (HTTP over TLS 的保留端口).origin 决定谁有权对以所标识资源为目标的请求作出权威响应, 如 Section 4.3.3 所定义.

发送方不得生成主机标识符为空的 "https" URI. 处理此类 URI 引用的接收方必须将其作为无效引用拒绝.

层次化 path 组件和可选 query 组件标识该源服务器命名空间内的目标资源.

客户端必须确保其针对 "https" 资源的 HTTP 请求在通信前已受到安全保护, 并且只接受这些请求的安全响应. 注意, 客户端和服务器可接受哪些密码机制通常通过协商确定, 并且可能随时间变化.

通过 "https" scheme 提供的资源与 "http" scheme 没有共享身份. 它们是不同的 origin, 具有独立命名空间. 然而, 某些定义为适用于同一主机所有 origin 的 HTTP 扩展, 如 Cookie 协议 [COOKIE], 允许一个服务设置的信息影响同一主机域匹配组内其他服务的通信. 设计此类扩展时应非常谨慎, 以防止从安全连接获得的信息被无意中在不安全上下文中交换.

4.2.3. http(s) 规范化和比较

带有 "http" 或 "https" scheme 的 URI 按 [URI] Section 6 中定义的方法进行规范化和比较, 并使用上文针对每个 scheme 描述的默认值.

HTTP 不要求使用特定方法来确定等价性. 例如, 缓存键可以作为简单字符串比较, 也可以在基于语法的规范化后比较, 或在基于 scheme 的规范化后比较.

"http" 和 "https" URI 的基于 scheme 的规范化 ([URI] Section 6.2.3) 涉及以下附加规则:

  • 如果端口等于某个 scheme 的默认端口, 规范形式是省略 port 子组件.

  • 当不作为 OPTIONS 请求目标使用时, 空 path 组件等价于 "/" 的绝对路径, 因此规范形式是提供 path "/".

  • scheme 和 host 不区分大小写, 通常以小写形式提供; 所有其他组件以区分大小写的方式比较.

  • 除 "reserved" 集合中字符之外的字符, 与其百分号编码的八位字节等价: 规范形式是不对它们进行编码 (见 [URI] Section 2.1 和 Section 2.2).

例如, 以下三个 URI 是等价的:

http://example.com:80/~smith/home.html
http://EXAMPLE.com/%7Esmith/home.html
http://EXAMPLE.com:/%7esmith/home.html

两个经规范化 (使用任意方法) 后等价的 HTTP URI 可以被假定标识同一资源, 并且任何 HTTP 组件都可以执行规范化. 因此, 不同资源不应由经规范化 (使用 [URI] Section 6.2 中定义的任意方法) 后等价的 HTTP URI 标识.

4.2.4. http(s) URI 中 userinfo 的弃用

authority 的 URI 通用语法还包括 userinfo 子组件 ([URI], Section 3.2.1), 用于在 URI 中包含用户认证信息. 在该子组件中, 使用 "user:password" 格式已被弃用.

有些实现会使用 userinfo 组件在内部配置认证信息, 例如在命令调用选项, 配置文件或书签列表中, 尽管这种用法可能暴露用户标识符或密码.

当在消息中把 "http" 或 "https" URI 引用生成为目标 URI 或字段值时, 发送方不得生成 userinfo 子组件 (及其 "@" 定界符).

在使用从不受信任来源收到的 "http" 或 "https" URI 引用之前, 接收方应解析是否存在 userinfo, 并把其存在视为错误; 它很可能被用于隐藏 authority 以进行钓鱼攻击.

4.2.5. 带片段标识符的 http(s) 引用

片段标识符允许间接标识次级资源, 且独立于 URI scheme, 如 [URI] Section 3.5 所定义. 有些引用 URI 的协议元素允许包含片段, 有些则不允许. 它们通过在允许片段的元素中使用相应 ABNF 规则来区分; 否则使用排除片段的特定规则.

注: 片段标识符组件不是 URI scheme 的 scheme 定义的一部分 (见 [URI] Section 4.3), 因此不会出现在上文 "http" 和 "https" URI scheme 的 ABNF 定义中.

4.3. 权威访问

权威访问指为了访问所标识资源而解引用给定标识符, 并且客户端认为这种访问是权威的 (由资源所有者控制). 确定是否授予访问的过程由 URI scheme 定义, 并且常使用 URI 组件中的数据, 例如使用通用语法时的 authority 组件. 然而, 权威访问不限于所标识的机制.

Section 4.3.1 定义了 origin 概念以辅助此类用途, 后续小节说明如何确定对等方有权代表某个 origin.

建立 authority 相关的安全考虑见 Section 17.1.

4.3.1. URI Origin

给定 URI 的 "origin" 是 scheme, host 和 port 的三元组, 其中 scheme 和 host 规范化为小写, port 规范化为去除任何前导零. 如果 URI 中省略 port, 则使用该 scheme 的默认 port. 例如, URI

https://Example.Com/happy.js

将具有 origin

{ "https", "example.com", "443" }

也可以描述为始终带有 port 的规范化 URI 前缀:

https://example.com:443

每个 origin 定义自己的命名空间, 并控制该命名空间中的标识符如何映射到资源. 反过来, origin 如何随时间一致地响应有效请求, 决定了用户会与某个 URI 关联的语义; 而这些语义的有用性最终把这些机制转化为用户未来可引用和访问的资源.

如果两个 origin 在 scheme, host 或 port 上不同, 则它们是不同的. 即使可以验证同一实体控制两个不同 origin, 这两个 origin 下的命名空间也是不同的, 除非由该 origin 的权威服务器显式设置别名.

Origin 也在 HTML 和相关 Web 协议中使用, 这些超出本文档范围, 如 [RFC6454] 所述.

4.3.2. http Origins

虽然 HTTP 独立于传输协议, 但 "http" scheme (Section 4.2.1) 专门用于把 authority 关联到这样一方: 它控制着 authority 组件中所标识任意主机上, 指示端口处侦听 TCP 连接的源服务器. 这是一种非常弱的 authority, 因为它依赖客户端特定的名称解析机制, 也依赖可能无法防止路径攻击者的通信. 尽管如此, 在受信任环境中, 这是把 "http" 标识符绑定到源服务器以实现一致解析的充分最低要求.

如果主机标识符以 IP 地址形式提供, 则源服务器是该 IP 地址上指示 TCP 端口处的侦听者 (如果存在). 如果 host 是注册名称, 则该注册名称是一个间接标识符, 用于通过 DNS 等名称解析服务查找适当源服务器的地址.

当在需要访问所指示资源的上下文中使用 "http" URI 时, 客户端可以尝试访问: 将主机标识符解析为 IP 地址, 建立到该地址上指示端口的 TCP 连接, 并通过该连接发送 HTTP 请求消息, 其中包含与客户端目标 URI (Section 7.1) 匹配的请求目标.

如果服务器以 Section 15 所述非临时 HTTP 响应消息响应该请求, 则该响应被视为对客户端请求的权威回答.

但请注意, 上述方式不是获得权威响应的唯一手段, 也不意味着总是需要权威响应 (见 [CACHING]). 例如, Alt-Svc 头字段 [ALTSVC] 允许源服务器标识也对该 origin 具有权威性的其他服务. 对 "http" 标识资源的访问也可能由本文档范围之外的协议提供.

4.3.3. https Origins

"https" scheme (Section 4.2.2) 基于服务器使用私钥的能力来关联 authority, 该私钥对应于客户端认为对所标识源服务器可信的证书. 客户端通常会依赖从某个预先安排或配置的信任锚传达的信任链, 来认为证书可信 (Section 4.3.4).

在 HTTP/1.1 及更早版本中, 只有当客户端通过一条成功建立且安全保护的连接进行通信, 并且该连接专门连接到 URI origin 的 host 时, 客户端才会把 authority 归于服务器. 连接建立和证书验证被用作 authority 证明.

在 HTTP/2 和 HTTP/3 中, 如果 URI origin 的 host 与服务器证书中存在的任一 host 匹配, 且客户端相信自己可以为该 URI 打开到该 host 的连接, 则客户端会在一条成功建立且安全保护的连接上通信时把 authority 归于服务器. 实际上, 客户端会执行 DNS 查询, 以检查 origin 的 host 是否包含与已建立连接相同的服务器 IP 地址. 源服务器可以通过发送等价的 ORIGIN frame [RFC8336] 移除此限制.

每个 HTTP 请求都会传递请求目标的 host 和 port 值, 用于标识 origin 并将其与同一服务器可能控制的其他命名空间区分开 (Section 7.2).origin 有责任确保任何被授予其证书私钥控制权的服务, 同样负责管理对应的 "https" 命名空间, 或至少准备好拒绝看起来被误导的请求 (Section 7.4).

即使源服务器对某些目标 URI 具有权威性, 它也可能不愿处理这些 URI 的请求. 例如, 当某个主机在不同端口上运行不同服务时 (例如 443 与 8000), 有必要在源服务器上检查目标 URI (即使连接已经受到安全保护), 因为网络攻击者可能导致某个端口的连接被其他端口接收. 不检查目标 URI 可能允许此类攻击者把一个目标 URI 的响应 (例如 "https://example.com/foo") 替换为来自另一个端口的看似权威响应 (例如 "https://example.com:8000/foo").

注意, "https" scheme 不依赖 TCP 和已连接端口号来关联 authority, 因为二者都在安全通信之外, 因而不能被视为确定可信. 因此, HTTP 通信可以发生在 Section 4.2.2 定义的任何安全通道之上, 包括不使用 TCP 的协议.

当在需要访问所指示资源的上下文中使用 "https" URI 时, 客户端可以尝试访问: 将主机标识符解析为 IP 地址, 建立到该地址上指示端口的 TCP 连接, 通过在 TCP 上成功发起具有机密性和完整性保护的 TLS 来端到端保护该连接, 并通过该连接发送 HTTP 请求消息, 其中包含与客户端目标 URI (Section 7.1) 匹配的请求目标.

如果服务器以 Section 15 所述非临时 HTTP 响应消息响应该请求, 则该响应被视为对客户端请求的权威回答.

但请注意, 上述方式不是获得权威响应的唯一手段, 也不意味着总是需要权威响应 (见 [CACHING]).

4.3.4. https 证书验证

为了建立安全连接来解引用 URI, 客户端必须验证服务身份是否可接受地匹配 URI 的源服务器. 证书验证用于防止路径攻击者或控制名称解析的攻击者冒充服务器. 此过程要求客户端配置有一组信任锚.

通常, 客户端必须使用 [RFC6125] Section 6 中定义的验证过程来验证服务身份. 客户端必须从服务的 host 构造引用身份: 如果 host 是字面 IP 地址 (Section 4.3.5), 则引用身份是 IP-ID; 否则 host 是名称, 引用身份是 DNS-ID.

客户端不得使用 CN-ID 类型的引用身份. 如 [RFC6125] Section 6.2.1 所述, CN-ID 类型引用身份可能被旧客户端使用.

客户端可以被专门配置为接受其他形式的服务器身份验证. 例如, 客户端可能连接到地址和主机名均为动态的服务器, 并期望该服务呈现特定证书 (或与某个外部定义引用身份匹配的证书), 而不是呈现与目标 URI 的 origin 匹配的证书.

在特殊情况下, 客户端简单地忽略服务器身份可能是合适的, 但必须理解这会使连接暴露于主动攻击.

如果证书对目标 URI 的 origin 无效, 用户代理必须在继续前获得用户确认 (见 Section 3.5), 或以错误证书错误终止连接. 自动化客户端必须将错误记录到适当的审计日志 (如果可用), 并且应以错误证书错误终止连接. 自动化客户端可以提供禁用此检查的配置设置, 但必须提供启用此检查的设置.

4.3.5. IP-ID 引用身份

在 "https" URI 的 "host" 字段中由字面 IP 地址标识的服务器具有 IP-ID 类型的引用身份. IP version 4 地址使用 "IPv4address" ABNF 规则, IP version 6 地址使用带有 "IPv6address" 选项的 "IP-literal" 产生式; 见 [URI] Section 3.2.2. IP-ID 的引用身份包含 IP 地址的解码字节.

IP version 4 地址为 4 个八位字节, IP version 6 地址为 16 个八位字节. IP-ID 的使用未为任何其他 IP version 定义. 证书 subjectAltName 扩展中的 iPAddress 选择不会显式包含 IP version, 而是依赖地址长度来区分版本; 见 [RFC5280] Section 4.2.1.6.

如果地址与证书 subjectAltName 扩展的 iPAddress 值相同, 则 IP-ID 类型的引用身份匹配.