HTTP 身份验证
HTTP 提供了一个用于访问控制和身份验证的通用框架。此页面介绍了用于身份验证的 HTTP 框架,并展示了如何使用 HTTP“Basic”方案限制对服务器的访问。
通用 HTTP 身份验证框架
RFC 7235 定义了 HTTP 身份验证框架,服务器可以使用该框架来 质询 客户端请求,客户端可以使用该框架来提供身份验证信息。
质询和响应流程如下所示
- 服务器使用
401
(未授权)响应状态回复客户端,并提供有关如何授权的信息,方法是使用包含至少一个质询的WWW-Authenticate
响应头。 - 想要向服务器进行身份验证的客户端可以通过在请求头中包含
Authorization
和凭据来实现。 - 通常,客户端会向用户显示密码提示,然后发出包含正确
Authorization
头的请求。
上述通用消息流对于大多数(如果不是全部)身份验证方案 都是相同的。头信息中的实际信息及其编码方式确实会发生变化!
警告:上图中使用的“Basic”身份验证方案会发送编码但未加密的凭据。除非交换是在安全连接(HTTPS/TLS)上进行,否则这将完全不安全。
代理身份验证
相同的质询和响应机制可用于代理身份验证。由于资源身份验证和代理身份验证可以共存,因此需要一组不同的头和状态代码。对于代理,质询状态代码为 407
(需要代理身份验证),Proxy-Authenticate
响应头包含至少一个适用于代理的质询,并且 Proxy-Authorization
请求头用于向代理服务器提供凭据。
访问被拒绝
如果(代理)服务器收到无效的凭据,则应使用 401
Unauthorized
或 407
Proxy Authentication Required
进行响应,用户可以发送新请求或替换 Authorization
头字段。
如果(代理)服务器收到有效但不足以访问给定资源的凭据,则服务器应使用 403
Forbidden
状态代码进行响应。与 401
Unauthorized
或 407
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-Authenticate
和 Proxy-Authenticate
响应头定义了应用于访问资源的身份验证方法。它们必须指定使用哪种身份验证方案,以便希望进行授权的客户端知道如何提供凭据。
这些头的语法如下所示
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
此处,<type>
是身份验证方案(“Basic”是最常见的方案,并在 下面介绍)。realm 用于描述受保护的区域或指示保护范围。这可能是一条消息,例如“访问登台站点”或类似消息,以便用户知道他们尝试访问哪个空间。
Authorization 和 Proxy-Authorization 头
Authorization
和 Proxy-Authorization
请求头包含用于对用户代理与(代理)服务器进行身份验证的凭据。此处,再次需要 <type>
,后跟凭据,这些凭据可以根据使用的身份验证方案进行编码或加密。
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
-
请参阅 RFC4599
- VAPID
-
请参阅 RFC 8292
- SCRAM
-
请参阅 RFC 7804
- AWS4-HMAC-SHA256
-
请参阅 AWS 文档。此方案用于 AWS3 服务器身份验证。
方案在安全性强度和客户端或服务器软件中的可用性方面可能有所不同。
“Basic”身份验证方案的安全性非常差,但支持广泛且易于设置。下面将详细介绍它。
基本身份验证方案
“Basic”HTTP 身份验证方案在 RFC 7617 中定义,该方案将凭据作为用户 ID/密码对传输,并使用 base64 进行编码。
基本身份验证的安全性
由于用户 ID 和密码作为明文通过网络传递(它是 base64 编码的,但 base64 是一种可逆编码),因此基本身份验证方案不安全。应将 HTTPS/TLS 与基本身份验证一起使用。如果没有这些额外的安全增强功能,则不应使用基本身份验证来保护敏感或有价值的信息。
使用 Apache 和基本身份验证限制访问
要对 Apache 服务器上的目录进行密码保护,您将需要一个 .htaccess
文件和一个 .htpasswd
文件。
.htaccess
文件通常如下所示
AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user
.htaccess
文件引用了一个 .htpasswd
文件,其中每一行都包含一个用户名和一个密码,用冒号 (:
) 分隔。您无法看到实际的密码,因为它们已 散列(在这种情况下,使用基于 MD5 的散列)。请注意,如果您愿意,可以将 .htpasswd
文件命名为其他名称,但请记住,此文件不应供任何人访问。(Apache 通常配置为阻止访问 .ht*
文件)。
aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/
使用 Nginx 和基本身份验证限制访问
对于 Nginx,您需要指定要保护的位置以及提供密码保护区域名称的 auth_basic
指令。然后,auth_basic_user_file
指令指向一个 .htpasswd
文件,其中包含加密的用户凭据,就像上面的 Apache 示例一样。
location /status {
auth_basic "Access to the staging site";
auth_basic_user_file /etc/apache2/.htpasswd;
}
使用 URL 中的凭据进行访问
许多客户端还允许您通过使用包含用户名和密码的编码 URL 来避免登录提示,如下所示
https://username:[email protected]/
不建议使用这些 URL。出于安全原因,Chrome 中的 URL 中的 username:password@
部分已 从子资源 URL 中删除。在 Firefox 中,它会检查站点是否确实需要身份验证,如果不需要,Firefox 会向用户发出提示“您即将使用用户名 username
登录到站点 www.example.com
,但该网站不需要身份验证。这可能是欺骗您的尝试。”如果站点确实需要身份验证,则 Firefox 仍会在将凭据发送到站点之前提示用户确认“您即将使用用户名 username
登录到站点 www.example.com
。”请注意,Firefox 在显示提示之前会先在两种情况下都不带凭据地发送请求,以确定站点是否需要身份验证。