跳到主要内容

11. HTTP 认证

11.1. 认证方案

HTTP 通过一组可扩展的质询-响应认证方案 (challenge-response authentication schemes), 为访问控制和认证提供了通用框架. 服务器可以使用这些方案来质询客户端请求, 客户端也可以使用这些方案来提供认证信息. 它使用大小写不敏感的 token 来标识认证方案:

auth-scheme    = token

除这个通用框架之外, 本文档不规定任何具体认证方案. 新的和已有的认证方案均独立规定, 并且应当注册到 "Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry" 中. 例如, "basic" 和 "digest" 认证方案分别由 [RFC7617] 和 [RFC7616] 定义.

11.2. 认证参数

认证方案后面会跟随通过该方案完成认证所必需的附加信息. 这些信息可以表示为以逗号分隔的参数列表, 也可以表示为一个能够承载 base64 编码信息的字符序列.

token68        = 1*( ALPHA / DIGIT /
"-" / "." / "_" / "~" / "+" / "/" ) *"="

token68 语法允许使用 66 个未保留 URI 字符 ([URI]) 以及少数其他字符, 因此它可以承载 base64, base64url (URL and filename safe alphabet), base32 或 base16 (hex) 编码, 可以带填充也可以不带填充, 但不包括空白字符 ([RFC4648]).

认证参数是名称/值对, 其中名称 token 以大小写不敏感的方式匹配, 并且每个参数名称在每个 challenge 中必须只出现一次.

auth-param     = token BWS "=" BWS ( token / quoted-string )

参数值可以表示为 "token", 也可以表示为 "quoted-string" (Section 5.6). 认证方案定义需要同时接受这两种记法, 对发送方和接收方都如此, 以便接收方无论认证方案如何, 都能使用通用解析组件.

为了向后兼容, 认证方案定义可以将发送方使用的格式限制为这两种变体之一. 当已知已部署的实现在遇到其中一种格式时会失败, 这种限制可能很重要.

11.3. 质询与响应

源服务器使用 401 (Unauthorized) 响应消息来质询用户代理的授权, 其中包含一个 WWW-Authenticate 头字段, 该字段至少包含一个适用于所请求资源的 challenge.

代理使用 407 (Proxy Authentication Required) 响应消息来质询客户端的授权, 其中包含一个 Proxy-Authenticate 头字段, 该字段至少包含一个适用于该代理处理所请求资源的 challenge.

challenge   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

Note: 许多客户端无法解析包含未知方案的 challenge. 解决此问题的一种办法是先列出受到广泛支持的方案 (例如 "basic").

希望向源服务器认证自身的用户代理, 通常但不一定是在收到 401 (Unauthorized) 之后, 可以通过在请求中包含 Authorization 头字段来完成认证.

希望向代理认证自身的客户端, 通常但不一定是在收到 407 (Proxy Authentication Required) 之后, 可以通过在请求中包含 Proxy-Authorization 头字段来完成认证.

11.4. 凭据

Authorization 字段值和 Proxy-Authorization 字段值都包含客户端针对所请求资源 realm 的凭据 (credentials), 这些凭据基于响应中收到的 challenge (可能是在过去某个时间点收到的). 创建这些值时, 用户代理应当选择它所理解的, 且它认为具有最安全 auth-scheme 的 challenge, 并在适当时从用户获取凭据. 在头字段值中传输凭据意味着对底层连接的机密性有重要安全考虑, 如 Section 17.16.1 所述.

credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

当源服务器收到针对受保护资源的请求, 而该请求省略凭据, 包含无效凭据 (例如错误密码), 或包含部分凭据 (例如认证方案需要多于一次往返) 时, 源服务器应该发送 401 (Unauthorized) 响应, 其中包含 WWW-Authenticate 头字段, 且该字段至少包含一个 (可能是新的) 适用于所请求资源的 challenge.

类似地, 当代理收到省略代理凭据, 或包含无效或部分代理凭据的请求时, 需要认证的代理应该生成 407 (Proxy Authentication Required) 响应, 其中包含 Proxy-Authenticate 头字段, 且该字段至少包含一个 (可能是新的) 适用于该代理的 challenge.

收到有效凭据但这些凭据不足以获得访问权限的服务器, 应当以 403 (Forbidden) 状态码响应 (Section 15.5.4).

HTTP 并不将应用程序限制在这种简单的质询-响应访问认证框架内. 还可以使用其他机制, 例如传输层认证或通过消息封装进行认证, 并配合指定认证信息的附加头字段. 不过, 本规范没有定义这些附加机制.

注意, 各种自定义用户认证机制会使用 [COOKIE] 中定义的 Set-Cookie 和 Cookie 头字段, 来传递与认证相关的 token.

11.5. 建立保护空间 (Realm)

"realm" 认证参数保留给希望指示保护作用域的认证方案使用.

保护空间 (protection space) 由被访问服务器的 origin (见 Section 4.3.1) 以及 realm 值 (如果存在) 共同定义. 这些 realm 允许将服务器上的受保护资源划分为一组保护空间, 每个保护空间都有自己的认证方案和/或授权数据库. realm 值是一个字符串, 通常由源服务器分配, 并且可以具有认证方案特定的附加语义. 注意, 一个响应可以包含多个具有相同 auth-scheme 但 realm 不同的 challenge.

保护空间决定了凭据可以自动应用的域. 如果先前某个请求已经获得授权, 用户代理可以在由认证方案, 参数和/或用户偏好 (例如可配置的非活动超时) 所确定的一段时间内, 对该保护空间内的所有其他请求复用相同凭据.

如果没有附加信息, 客户端不一定知道保护空间的范围, 因而也不一定知道凭据可能被自动应用到哪些请求. 认证方案可以定义描述保护空间范围的参数. 除非认证方案明确允许, 单个保护空间不能扩展到其服务器的作用域之外.

出于历史原因, 发送方必须只生成 quoted-string 语法. 为了与长期接受两种记法的现有客户端实现达到最大互操作性, 接收方可能必须同时支持 token 和 quoted-string 语法.

11.6. 向源服务器认证用户

11.6.1. WWW-Authenticate

"WWW-Authenticate" 响应头字段指示适用于目标资源的认证方案及其参数.

WWW-Authenticate = #challenge

生成 401 (Unauthorized) 响应的服务器必须发送一个 WWW-Authenticate 头字段, 其中至少包含一个 challenge. 服务器可以在其他响应消息中生成 WWW-Authenticate 头字段, 以指示提供凭据 (或不同的凭据) 可能会影响响应.

转发响应的代理不得修改该响应中的任何 WWW-Authenticate 头字段.

建议用户代理在解析字段值时格外谨慎, 因为它可能包含多个 challenge, 并且每个 challenge 都可以包含一个以逗号分隔的认证参数列表. 此外, 该头字段本身也可以出现多次.

例如:

WWW-Authenticate: Basic realm="simple", Newauth realm="apps",
type=1, title="Login to \"apps\""

此头字段包含两个 challenge, 一个用于 "Basic" 方案且 realm 值为 "simple", 另一个用于 "Newauth" 方案且 realm 值为 "apps". 它还包含两个附加参数, "type" 和 "title".

不过, 某些用户代理无法识别这种形式. 因此, 在同一字段行上发送包含多个成员的 WWW-Authenticate 字段值可能无法互操作.

Note: challenge 语法产生式也使用列表语法. 因此, 逗号, 空白和逗号组成的序列既可以被视为应用于前一个 challenge, 也可以被视为空的 challenge 列表项. 在实践中, 这种歧义不会影响头字段值的语义, 因而是无害的.

11.6.2. Authorization

"Authorization" 头字段允许用户代理向源服务器认证自身, 通常但不一定是在收到 401 (Unauthorized) 响应之后. 它的值由凭据组成, 这些凭据包含用户代理针对所请求资源 realm 的认证信息.

Authorization = credentials

如果一个请求已经过认证并且指定了 realm, 则假定相同凭据对该 realm 内的所有其他请求都有效 (前提是认证方案本身没有其他要求, 例如凭据会根据 challenge 值变化或使用同步时钟).

转发请求的代理不得修改该请求中的任何 Authorization 头字段. 关于 HTTP 缓存处理 Authorization 头字段的细节和相关要求, 见 [CACHING] 的 Section 3.5.

11.6.3. Authentication-Info

HTTP 认证方案可以使用 "Authentication-Info" 响应字段, 在客户端的认证凭据被接受后传递信息. 这些信息可以包括来自服务器的最终消息 (例如, 它可以包含服务器认证).

字段值是参数列表 (名称/值对), 使用 Section 11.3 中定义的 "auth-param" 语法. 本规范只描述通用格式; 使用 Authentication-Info 的认证方案会定义各自的具体参数. 例如, "Digest" 认证方案在 [RFC7616] 的 Section 3.5 中定义了多个参数.

Authentication-Info = #auth-param

Authentication-Info 字段可以用于任何 HTTP 响应, 与请求方法和状态码无关. 它的语义由对应请求的 Authorization 头字段 (Section 11.6.2) 所指示的认证方案定义.

转发响应的代理不得以任何方式修改该字段值.

当认证方案明确允许时, Authentication-Info 可以作为 trailer field (Section 6.5) 发送.

11.7. 向代理认证客户端

11.7.1. Proxy-Authenticate

"Proxy-Authenticate" 头字段由至少一个 challenge 组成, 用于指示适用于此请求中该代理的认证方案及其参数. 代理在生成的每个 407 (Proxy Authentication Required) 响应中, 必须至少发送一个 Proxy-Authenticate 头字段.

Proxy-Authenticate = #challenge

与 WWW-Authenticate 不同, Proxy-Authenticate 头字段只适用于响应链上的下一个出站客户端. 这是因为只有选择给定代理的客户端才可能拥有认证所需的凭据. 但是, 当多个代理在同一管理域内使用时, 例如大型企业网络中的办公室和区域缓存代理, 通常由用户代理生成凭据并沿层次结构传递, 直到被消费. 因此, 在这种配置中, Proxy-Authenticate 看起来像是在被转发, 因为每个代理都会发送相同的 challenge 集合.

注意, WWW-Authenticate 的解析注意事项也适用于此头字段; 详情见 Section 11.6.1.

11.7.2. Proxy-Authorization

"Proxy-Authorization" 头字段允许客户端向需要认证的代理标识自身 (或其用户). 它的值由凭据组成, 这些凭据包含客户端针对该代理和/或所请求资源 realm 的认证信息.

Proxy-Authorization = credentials

与 Authorization 不同, Proxy-Authorization 头字段只适用于使用 Proxy-Authenticate 头字段要求认证的下一个入站代理. 当链中使用多个代理时, Proxy-Authorization 头字段会被第一个期待接收凭据的入站代理消费. 如果代理之间正是通过这种机制协作认证给定请求, 代理可以将来自客户端请求的凭据中继给下一个代理.

11.7.3. Proxy-Authentication-Info

"Proxy-Authentication-Info" 响应头字段等价于 Authentication-Info, 但它适用于代理认证 (Section 11.3), 并且它的语义由对应请求的 Proxy-Authorization 头字段 (Section 11.7.2) 所指示的认证方案定义:

Proxy-Authentication-Info = #auth-param

不过, 与 Authentication-Info 不同, Proxy-Authentication-Info 头字段只适用于响应链上的下一个出站客户端. 这是因为只有选择给定代理的客户端才可能拥有认证所需的凭据. 但是, 当多个代理在同一管理域内使用时, 例如大型企业网络中的办公室和区域缓存代理, 通常由用户代理生成凭据并沿层次结构传递, 直到被消费. 因此, 在这种配置中, Proxy-Authentication-Info 看起来像是在被转发, 因为每个代理都会发送相同的字段值.

当认证方案明确允许时, Proxy-Authentication-Info 可以作为 trailer field (Section 6.5) 发送.