导航
HTTP 认证之基本认证 --Basic(一)
HTTP 认证之基本认证 --Basic(二)
HTTP 认证之摘要认证 --Digest(二)
一, 概述
Digest 认证是为了修复基本认证协议的严重缺陷而设计的, 秉承 "绝不通过明文在网络发送密码" 的原则, 通过 "密码摘要" 进行认证, 大大提高了安全性.
相对于基本认证, 主要有如下改进:
绝不通过明文在网络上发送密码
可以有效防止恶意用户进行重放攻击
可以有选择的防止对报文内容的篡改
需要注意的是, 摘要认证除了能够保护密码之外, 并不能保护其他内容, 与 HTTPS 配合使用仍是一个良好的选择. 以下是摘要认证的具体流程图:
看到上面出现了那么多之前没见过的参数, 是不是有点慌(或是兴奋)? 别着急, 这里先给出一个概览:
WWW-Authentication: 用来定义使用何种方式 (Basic,Digest,Bearer 等) 去进行认证以获取受保护的资源
realm: 表示 web 服务器中受保护文档的安全域(比如公司财务信息域和公司员工信息域), 用来指示需要哪个域的用户名和密码
qop: 保护质量, 包含 auth(默认的)和 auth-int(增加了报文完整性检测)两种策略,(可以为空, 但是)不推荐为空值
nonce: 服务端向客户端发送质询时附带的一个随机数, 这个数会经常发生变化. 客户端计算密码摘要时将其附加上去, 使得多次生成同一用户的密码摘要各不相同, 用来防止重放攻击
nc:nonce 计数器, 是一个 16 进制的数值, 表示同一 nonce 下客户端发送出请求的数量. 例如, 在响应的第一个请求中, 客户端将发送 "nc=00000001". 这个指示值的目的是让服务器保持这个计数器的一个副本, 以便检测重复的请求
cnonce: 客户端随机数, 这是一个不透明的字符串值, 由客户端提供, 并且客户端和服务器都会使用, 以避免用明文文本. 这使得双方都可以查验对方的身份, 并对消息的完整性提供一些保护
response: 这是由用户代理软件计算出的一个字符串, 以证明用户知道口令
Authorization-Info: 用于返回一些与授权会话相关的附加信息
nextnonce: 下一个服务端随机数, 使客户端可以预先发送正确的摘要
rspauth: 响应摘要, 用于客户端对服务端进行认证
stale: 当密码摘要使用的随机数过期时, 服务器可以返回一个附带有新随机数的 401 响应, 并指定 stale=true, 表示服务器在告知客户端用新的随机数来重试, 而不再要求用户重新输入用户名和密码了
二, 剖析
1. 当打开需要认证的页面时, 会弹出一个对话框, 要求用户输入用户名和密码
2. 使用 Fidder 监听请求, 可以看到在未进行认证或认证失败的情况下, 服务端会返回 401 Unauthorized 给客户端, 并附带 Challenge
3. 输入正确的用户名和密码后, 浏览器会生成密码摘要以及其他信息发送给服务端, 服务端认证成功后, 返回一些与授权会话相关的附加信息, 放在 Authorization-Info 中.
其中, 客户端选择的保护质量策略为 auth,response 就是通过计算得到的密码摘要, 具体计算方式如下(使用默认的 MD5 加密算法):
MD5(MD5(A1):<nonce>:<nc>:<cnonce>:<qop>:MD5(A2))
算法 | A1 |
---|---|
MD5(默认) | <username>:<realm>:<password> |
MD5-sess | MD5(<username>:<realm>:<password>):<nonce>:<cnonce> |
qop | A2 |
---|---|
auth(默认) | <request-method>:<uri> |
auth-int | <request-method>:<uri>:MD5(<request-entity-body>) |
另外, rspauth 使得客户端可以对服务器进行认证, 称为响应摘要. 响应摘要的计算与请求摘要类似, 但由于响应中没有方法, 而且报文实体数据有所不同, 所有只有报文主题信息 A2 不同. 具体区别如下:
qop | A2 |
---|---|
auth(默认) | :<uri> |
auth-int | :<uri>:MD5(<response-entity-body>) |
4. 当服务端随机数过期时, 再次请求认证, 可以看到质询中增加了 stale=true, 用户无需再次输入用户名和密码, 浏览器会自动使用新的质询参数进行密码摘要的计算.
三, 注意事项
1. 预授权: 服务端预先告知客户端下一个随机数是多少, 使得客户端可以直接生成正确的 Authorization 首部, 避免了多次 "请求 / 质询". 常用的有一下三种方式:
服务器预先在 Authorization-Info 成功首部中发送下一个随机数 nextnonce. 虽然这种机制加快了事务处理的速度, 但是它也破坏了对同一台服务器的多次请求进行管道化的功能, 可能会造成很大的损失.
服务器允许在一小段时间内使用同一个随机数. 这也就是我们上面剖析中使用的机制, 在一定时间内使用同一个随机数或限制某个随机数的重用次数, 当过期时, 声明 stale=true. 虽然这确实降低了安全性, 但是重用的随机数的生存周期是可控的, 应该在安全和性能之间找到平衡.
客户端和服务器使用同步的, 可预测的随机数生成算法.
2.RFC 2617 建议采用这个假想的随机数公式:
BASE64(timestamp MD5(timestamp ":" ETag ":" private-key))
其中, timestamp 是服务器产生随机数的时间或其他不重复的值, ETag 是与所请求实体有关的 HTTP ETag 首部的值, private-key 是只有服务器知道的私钥.
来源: https://www.cnblogs.com/xiaoxiaotank/p/11078571.html