Web 上对于一些私人数据,获取时需要进行用户认证,即要用户名和密码,才能访问资源。浏览器上可以通过 Cookie 来进行认证,移动客户端没有 Cookie,可以使用 HTTP 原生提供的一些认证机制。

这里介绍两种最常见的 HTTP 认证形式,基本认证(basic authentication)和摘要认证(digest authentication)。

1. 认证协议与首部

HTTP 通过一组可定制的控制首部,为不同的认证协议提供了一个可扩展框架。

步骤 首部 描述 方法/状态
请求 第一条请求没有认证信息 GET
质询 WWW-Authenticate 服务器需要用户提供认证 401 Unauthorized
授权 Authorization 客户端发出带认证的请求 GET
成功 Authentication-Info 如果认证成功,则请求成功 200 OK

服务器质询时,会告诉客户端应该如何认证,质询信息就在返回的 WWW-Authenticate 首部字段中,里面包含了一个 realm 指令,告诉客户端是在应该在哪个域下进行认证。很多公司都会有不同的安全域,普通员工一个域,财务部一个域,那么如果财务访问资源,如果未认证,就应该提示客户端用财务部账号授权认证。

1
2
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Corporate Financials"

对一些高级认证算法来说,认证成功后,可能还会返回一些额外的与授权回话相关的信息,这些信息会放在 Authentication-Info 字段中。

2. 基本认证

基本认证是最流行的 HTTP 认证协议,最初是在 HTTP/1.0 规范中提出的。

2.1 Base64 编码

基本认证是将用户名和密码以冒号分隔,用 Base64 编码将其打包一起。

1
String encodeAuth = Base64.encode(username:password)

将编码后的信息作为认证信息,发给服务端。

1
Authorization: Basic encodeAuth

服务器在对认证信息进行 Base64 解码,获取出用户名密码来验证。

2.2 代理认证

代理服务器也可以实现认证功能。步骤与 Web 服务器身份验证的步骤相同。但首部和状态码都有所不同。

Web 服务器 代理服务器
Unauthorized status code: 401 Unauthorized status code: 407
WWW-Authenticate Proxy-Authenticate
Authorization Proxy-Authorization
Authentication-Info Proxy-Authentication-Info

通过代理服务器提供对某组织内部资源的统一访问控制是一种很便捷的方式。

2.3 缺陷

基本认证简单方便,但并不安全。

  • Base64 编码隐可以很容易被解码,实际上,用户名密码就是以「明文」的形式传输的,安全隐患很大。
  • 重放攻击。第三方用户获取到用户名和密码后,可以一次一次地重放给原始服务器,以获得对服务器的访问权。
  • 没有针对代理的防护措施,代理没有修改认证首部,但可能修改了报文的其余部分,这样就严重地改变了事务的本质。
  • ……

为了避免以上缺陷,可以使用更安全的认证协议,比如摘要认证。

3. 摘要认证

摘要认证并不是最安全的协议,至今也还没有被广泛应用,但摘要认证比它要取代的基本认证强大很多。

  • 永远不会以明文的方式发送密码
  • 可以防止恶意用户捕获并重放认证的握手过程
  • 可以有选择的防止对报文内容的修改
  • 防范其它几种常见的攻击方式

摘要认证不能满足安全 HTTP 事务的很多需求。对这些需求来说,使用 TLS (Transport Layer Security) 和HTTPS (Secure HTTP) 协议更为合适一些。

3.1 工作原理

摘要认证不发送密码,而是发送一个「指纹」或密码的「摘要」,这个「摘要」是不可逆的。服务端根据用户信息可以计算得出一个「摘要」来,与客户端发送过来的「摘要」比对,如果匹配则认证通过。

常见的摘要函数 MD5,即将任意长度的字节序列转换为一个 128 位的摘要。这 128 位的摘要通常会被写成 32 个十六进制的字符,每个字符表示 4 位。

3.2 用随机数避免重放攻击

仅仅使用摘要,恶意用户仍然可以捕获并重发请求,这和密码就一样了。为了防止此类重放攻击的发生,服务器可以在 WWW-Authenticate 字段中向客户端发送一个随机数(nonce)的特殊令牌,客户端在计算摘要之前,要先将这个令牌附加到密码上去。

而且这个随机数会经常发生变化(可能每次认证都变化),这样每次的认证「摘要」都不一样,从而防止重放攻击的发生

3.3 握手机制

摘要认证,在返回头部添加了一个新的可选首部 Authentication-Info,可以存放客户端下一次请求的随机数。

摘要认证整体的流程:

  1. 客户端请求,未带授权信息
  2. 服务器将发出质询,并在 WWW-Authenticate 首部发送一个随机数和服务端支持的摘要算法列表
  3. 客户端选择一个算法,计算出密码的摘要。并将摘要放在 Authorization 首部字段中,和数据一起发回服务器。如果客户端要对服务器进行认证,可以发送一个客户端随机数。
  4. 服务器接收到摘要、选中的算法以及数据后,计算出一个的摘要,然后将本地计算的摘要与传送过来的摘要进行比较,验证是否匹配。
  5. 匹配后,如果有客户端的随机数对服务器进行质询,服务端就会创建客户端摘要,并且可以预先将下一个随机数计算出来,提前将其传递给客户端,这样下一次客户端就可以预先发送正确的摘要了。

3.4 缺陷

  • 服务端预先生成随机数,虽然可以减少请求,加快处理速度,但是却破坏了 HTTP 的管道化机制,因为在发布下一条请求之前,一定要收到下一个随机值才行。这样会造成很大的性能损失。
  • 如果不采用每次请求都用随机数,而是在有限的次数内重用随机数。比如,允许将某个随机数重用 5 次,或者重用 10 秒,仍然有一定的重放攻击隐患。

参考