HTTP协议本身对于可能遇到的安全方面的问题也有一些这方面的设计,虽然并不完善,不过对于大多数的网站已经可以适用。如果是其他的加密协议,在调试方面会比较麻烦,需要自己设计拆包和解密的工具,那还不如彻底用好HTTP的协议。
摘要认证是另一种HTTP认证协议,相对于HTTP基本认证复杂的多,它对于认证协议增加了许多改进。
摘要认证比基本认真强大的多,与很多建议其他因特网服务使用的常用策略相比(比如曾建议LDAP、POP和IMAP使用的CRAM-MD5),摘要认真也强大的多。
摘要认证的特点简单总结就是以下几点:
- 永远不会以明文方式发送密码,特别是完整密码
- 有特定方式防止恶意用户捕获并重放认证
- 有能力防止报文被篡改
- 可以防范其他一些常见攻击方式
摘要认真对于资源请求的认证过程和基本认证都是一样的,有四步基本过程(可以参考上一篇博文)。:
- 客户端发送请求
- 服务器应答告知需要授权
- 客户端发送认证信息(密码等)
- 服务器验证认证信息
跟基本认证不同的地方在于摘要认证不提供完整的密码,只提供对于用户名、密码或其他认证信息的指纹信息,比如MD5摘要。服务器使用和客户端相同的函数进行计算,如果结果相同则通过验证。
为了防止重放攻击,摘要认证要求必须使用随机数。
这个数会经常发生变化(可能是每毫秒,或者是每次认证都变化)。客户端在计算摘要之前要先将这个随机数令牌附加到密码上去。
因为通常使用单向摘要算法,所以攻击者拦截了网络包也无法真正获取到密码,而没有密码就无法计算正确摘要,保护了客户端的认证信息。
在摘要认证中,所有的验证信息都是放在HTTP包的头部。
下面简要解释各个步骤的头部验证信息:
第一步,客户端发送请求,不需要发生验证信息;
第二步,服务器应答码:401,并在头部中添加WWW-Authenticate指令
- WWW-Authenticate
- realm:显示给用户,可能是主机名,也可能是被访问的集合。用于提示用户需要验证的资源
- nonce:每次401都带着,通常是时间戳、ETag以及私密信息构造出的Base-64编码
- domain:URI列表,用于定义保护空间,指示同样的验证信息发送给哪个URI集(可为空)
- opaque:服务器指定的数据串,客户端应该不经修改直接放在后续请求中
- stale:true/false/没有。false,说明验证信息无效;true,nonce过旧,但摘要有效;没有这一项,代表用户名密码无效
- algorithm:摘要和校验码算法(可为空,默认为MD5)
- qop:auth/auth-int。定义了与报文有关的数据的摘要生成方式(可为空)
第三步,客户端发送验证信息
- Authorization
- username:指定域中的用户名
- realm:在WWW-Authenticate首部传送给客户端的域
- nonce:和WWW-Authenticate首部相同的nonce
- uri:请求的uri
- response:摘要认证的重点,由密码等信息计算出的摘要
- algorithm:说明摘要和校验和的一对算法(可为空,默认为md5)
- opaque:WWW-Authenticate中指定的数据串,应该由客户端不经修改的在后继请求的WWW-Authenticate中返回
- cnonce:和qop配合使用(同时有或者同时没有),用以提供双向认证以及报文一致性检查
- qop:说明客户端对报文应用的“安全保障”,使用WWW-Authenticate中qop支持的可选值之一
- nc:和qop同时出现,表示客户端已经发送的含nonce值的次数
第四步,服务器端返回验证后的结果
- Authentication-Info
- nextnonce:服务器发送的下次使用的nonce
- qop:同WWW-Authenticate的意义一样
- rspauth:同qop同时出现,对于报文内容进行完整性保护
- cnonce:跟客户端发送的cnonce相同
- nc:同qop同时出现,跟客户的请求的一致
有关第三步如何计算response可以参考详解HTTP中的摘要认证机制,本文中选择algorithm为默认的md5,qop使用未定义。
敬请期待下一篇博文:Node.js实践HTTP安全认证之三~~摘要认真(实践)
参考:
1. Http权威指南
2. JavaScript生成GUID的算法
3. 使用js生成GUID
4. 博文共赏:Node.js静态文件服务器实战
5. javascript base64 encode and decode
6. 详解HTTP中的摘要认证机制