HTTP 身份验证

HTTP 为访问控制和认证提供了一个通用框架。本页面介绍了 HTTP 认证框架,并展示了如何使用 HTTP “Basic” 方案限制对服务器的访问。

通用 HTTP 认证框架

RFC 7235 定义了 HTTP 认证框架,服务器可以使用该框架质询客户端请求,客户端也可以提供认证信息。

质询和响应流程如下所示:

  1. 服务器向客户端发送 401 (Unauthorized) 响应状态,并提供如何使用 WWW-Authenticate 响应头进行授权的信息,该响应头至少包含一个质询。
  2. 希望向服务器进行认证的客户端可以通过包含带有凭据的 Authorization 请求头来完成此操作。
  3. 通常,客户端会向用户显示密码提示,然后发出包含正确 Authorization 头的请求。

A sequence diagram illustrating HTTP messages between a client and a server lifeline.

上述通用消息流对于大多数(如果不是全部)认证方案都是相同的。但是,头部中的实际信息及其编码方式会发生变化!

警告: 上图中使用的“Basic”认证方案发送的凭据是经过编码但未加密的。除非通过安全连接 (HTTPS/TLS) 进行交换,否则这将完全不安全。

代理认证

相同的质询和响应机制也可用于代理认证。由于资源认证和代理认证可以共存,因此需要一套不同的头部和状态码。在代理的情况下,质询状态码是 407 (Proxy Authentication Required),Proxy-Authenticate 响应头包含至少一个适用于代理的质询,而 Proxy-Authorization 请求头用于向代理服务器提供凭据。

禁止访问

如果(代理)服务器收到无效凭据,它应该响应 401 Unauthorized407 Proxy Authentication Required,用户可以发送新请求或替换 Authorization 头部字段。

如果(代理)服务器收到有效但不足以访问给定资源的凭据,服务器应该响应 403 Forbidden 状态码。与 401 Unauthorized407 Proxy Authentication Required 不同,该用户无法进行认证,浏览器也不会提议再次尝试。

在所有情况下,服务器都可能倾向于返回 404 Not Found 状态码,以向没有足够权限或未正确认证的用户隐藏页面的存在。

跨域图像的认证

一个潜在的安全漏洞(后来在浏览器中得到修复)是跨站图像的认证。从 Firefox 59 开始,从与当前文档不同来源加载的图像资源不再能够触发 HTTP 认证对话框 (Firefox bug 1423146),从而防止攻击者能够将任意图像嵌入到第三方页面时窃取用户凭据。

HTTP 认证的字符编码

浏览器对用户名和密码使用 utf-8 编码。

Firefox 曾经使用 ISO-8859-1,但为了与其他浏览器保持一致并避免 Firefox bug 1419658 中描述的潜在问题,已更改为 utf-8

WWW-Authenticate 和 Proxy-Authenticate 头部

WWW-AuthenticateProxy-Authenticate 响应头定义了应如何使用认证方法来获取资源访问权限。它们必须指定使用哪种认证方案,以便希望授权的客户端知道如何提供凭据。

这些头部的语法如下:

http
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>

在此,<type> 是认证方案(“Basic”是最常见的方案,并在下面介绍)。realm 用于描述受保护区域或指示保护范围。这可能是一条消息,如“访问暂存站点”或类似内容,以便用户知道他们正在尝试访问哪个空间。

Authorization 和 Proxy-Authorization 头部

AuthorizationProxy-Authorization 请求头包含用于向(代理)服务器认证用户代理的凭据。在此,再次需要 <type>,后跟凭据,凭据可以根据所使用的认证方案进行编码或加密。

http
Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>

认证方案

通用的 HTTP 认证框架是许多认证方案的基础。

IANA 维护着一份认证方案列表,但主机服务(如 Amazon AWS)也提供其他方案。

一些常见的认证方案包括:

Basic

参见 RFC 7617,base64 编码的凭据。更多信息见下文。

Bearer

参见 RFC 6750,用于访问 OAuth 2.0 保护资源的承载令牌。

Digest

参见 RFC 7616。Firefox 93 及更高版本支持 SHA-256 算法。早期版本仅支持 MD5 哈希(不推荐)。

HOBA

参见 RFC 7486 第 3 节,HTTP Origin-Bound Authentication,基于数字签名。

Mutual

参见 RFC 8120

Negotiate / NTLM

参见 RFC4559

VAPID

参见 RFC 8292

SCRAM

参见 RFC 7804

AWS4-HMAC-SHA256

参见 AWS 文档。此方案用于 AWS3 服务器认证。

方案在安全强度以及客户端或服务器软件中的可用性方面可能有所不同。

“Basic”认证方案提供的安全性很差,但它得到广泛支持且易于设置。下面将更详细地介绍它。

基本认证方案

“Basic” HTTP 认证方案定义在 RFC 7617 中,它将凭据以用户 ID/密码对的形式传输,使用 base64 编码。

基本认证的安全性

由于用户 ID 和密码以明文形式通过网络传输(尽管它是 base64 编码的,但 base64 是一种可逆编码),因此基本认证方案不安全。应将 HTTPS/TLS 与基本认证结合使用,以防止凭据被截获。

此外,使用 HTTP 基本认证的网站特别容易受到跨站请求伪造 (CSRF) 攻击,因为无论来源如何,用户凭据都会在所有请求中发送(这与基于 cookie 的凭据机制不同,因为 cookie 通常在跨站请求中被阻止)。网站在更改数据时应始终使用 POST 请求,并包含 CSRF 令牌

如果没有这些安全增强功能,不应使用基本认证来保护敏感或有价值的信息。

使用 Apache 和基本认证限制访问

要在 Apache 服务器上对目录进行密码保护,您需要一个 .htaccess 文件和一个 .htpasswd 文件。

.htaccess 文件通常如下所示:

apacheconf
AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user

.htaccess 文件引用了一个 .htpasswd 文件,其中每行包含一个用户名和一个密码,用冒号 (:) 分隔。您无法看到实际的密码,因为它们已被哈希(在这种情况下使用基于 MD5 的哈希)。请注意,如果您愿意,可以为 .htpasswd 文件命名不同,但请记住此文件不应被任何人访问。(Apache 通常配置为阻止访问 .ht* 文件)。

apacheconf
aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/

使用 Nginx 和基本认证限制访问

对于 Nginx,您需要指定要保护的位置,以及提供密码保护区域名称的 auth_basic 指令。然后,auth_basic_user_file 指令指向一个包含加密用户凭据的 .htpasswd 文件,就像上面的 Apache 示例一样。

apacheconf
location /status {
    auth_basic           "Access to the staging site";
    auth_basic_user_file /etc/apache2/.htpasswd;
}

使用 URL 中的凭据访问

历史上,一些网站允许您使用包含用户名和密码的编码 URL 登录,如下所示:

https://username:password@www.example.com/

现代浏览器不再允许这种语法;在发送请求之前,用户名和密码会从请求中剥离。

另见