用户身份认证
1. 概述
计算机本身无法判断坐在显示器前的使用者的身份。进一步说,也无法确认网络的那头究竟有谁。可见,为了弄清究竟是谁在访问服务器,就得让对方的客户端自报家门。
通常通过核对以下信息来核实用户信息(但是,即便对方是假冒的用户,只要能通过用户验证,那么计算机就会默认是出自本人的行为。因此,掌控机密信息的密码绝不能让他人得到,更不能轻易地就被破解出来):
- 密码:只有本人才会知道的字符串信息
- 动态令牌:仅限本人持有的设备内显示的一次性密码
- 数字证书:仅限本人(终端)持有的信息
- 生物认证:指纹和虹膜等本人的生理信息
- IC 卡等:仅限本人持有的信息
HTTP 有 7 种最常见的用来承载用户相关信息的 HTTP 请求首部:
首部名称 | 首部类型 | 描述 |
---|---|---|
From | 请求 | 用户的 E-mail 地址 |
User-Agent | 请求 | 用户的浏览器软件 |
Referer | 请求 | 用户是从这个页面上依照链接跳转过来的 |
Authorization | 请求 | 用户名和密码 |
Client-IP | 扩展(请求) | 客户端的 IP 地址 |
X-Forwarded-For | 扩展(请求) | 客户端的 IP 地址 |
Cookie | 扩展(请求) | 服务器产生的 ID 标签 |
不考虑使用用户 IP 地址、email 地址等这些明显带有缺陷的方式。Web 服务器无需被动地根据用户的 IP 地址来猜测他的身份,它可以要求用户通过用户名和密码进行认证(登录)来显式地询问用户是谁。这里边主要有两种方式(哥们自己这么总结认为的):
- 一种是 Cookie 的方式,这里不再赘述;
- 另一种是,为了使 Web 站点的登录更加简便,HTTP 中包含了一种内建机制,可以借助
WWW-Authenticate
响应首部和Authorization
请求首部向 Web 站点传送用户的相关信息。一旦登录,浏览器就可以不断地在每条发往这个站点的请求中发送这个登录信息了,这样,就总是有登录信息可用了。
这里着重阐述使用 Authorization
的方式。
2. HTTP 的质询/响应认证框架
RFC 7235 定义了一个 HTTP 身份验证框架——质询/ 响应(challenge/response)框架。服务器可以质询(challenge)客户端的请求,客户端则可以提供身份验证凭据。
质询与响应的工作流程整体可示意如下:
- 客户端发起请求;
- 服务器端向客户端返回
401
(Unauthorized,未被授权的)响应状态码,并在WWW-Authenticate
响应标头提供如何进行验证的信息,其中至少包含有一种质询方式; - 之后,想要使用服务器对自己身份进行验证的客户端,可以通过包含凭据的
Authorization
请求标头进行验证; - 通常,客户端会向用户显示密码提示,然后发送包含正确的
Authorization
标头的请求。
与上述同样的质询/响应原理也适用于代理认证。由于资源认证和代理认证可以并存,为了在标头和响应状态码上进行区别,对于代理,质询的状态码是 407
(必须提供代理证书),响应标头 Proxy-Authenticate
至少包含一个可用的质询,并且用请求标头 Proxy-Authorization
向代理服务器提供凭据。
如果(代理)服务器收到无效的凭据,它应该响应 401 Unauthorized
或 407 Proxy Authentication Required
,此时用户可以发送新的请求或替换 Authorization
标头字段;如果(代理)服务器接受的有效凭据不足以访问给定的资源,服务器将响应 403 Forbidden
状态码,与 401 Unauthorized
或 407 Proxy Authentication Required
不同的是,该用户无法进行身份验证并且浏览器不会提出新的的尝试。然而,很多情况下,服务器也可能返回 404 Not Found
状态码,以向没有足够权限或者未正确身份验证的用户隐藏页面的存在。
3. 首部字段
WWW-Authenticate
与 Proxy-Authenticate
响应标头指定了为获取资源访问权限而进行身份验证的方法。它们需要明确要进行验证的方案,这样希望进行授权的客户端就知道该如何提供凭据。
这两个标头的语法形式如下:
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
其中:
<type>
指的是验证的方案(如Basic
)<realm>
用来描述进行保护的区域,或者指代保护的范围。它可以是类似于“Access to the staging site”的消息,这样用户就可以知道他们正在试图访问哪一空间。
Authorization
与 Proxy-Authorization
请求标头包含有用来向(代理)服务器证明用户代理身份的凭据。这里同样需要指明验证的 <type>
,其后跟有凭据信息,该凭据信息可以被编码或者加密,取决于采用的是哪种认证方案。
Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>
4. 认证方案
HTTP 的质询/响应身份认证框架有多种认证方案(Authentication scheme)。不同的认证方案在安全强度以及在客户端或服务器端软件中可获得的难易程度上有所不同。常见的认证方案包括:
Basic
:参见 RFC 7617,base64 编码凭据,其实就是将由冒号:
分隔的用户名和密码打包在一起,并用 Base-64 编码方式对其进行编码,即:$Base64(username:password)$Digest
:参见 RFC 7616,Firefox 93 及更高版本支持 SHA-256 算法。以前的版本仅支持 MD5 散列(不建议)。Bearer
:参见 RFC 6750,bearer 令牌通过 OAuth 2.0 保护资源。HOBA
:参见 RFC 7486,阶段三,HTTP Origin-Bound 认证,基于数字签名。Mutual
:参见 RFC 8120Negotiate / NTLM
:参见 RFC4599VAPID
:参见 RFC 8292SCRAM
:参见 RFC 7804- ...