0. 背景
计算机本身无法判断坐在显示器前的使用者的身份,也无法确认网络的另一端的是谁。为了明确是谁在访问服务器,必须让客户端自报家门。
通常核对一些登录者本人的信息:
- 密码:只有本人知道的字符串信息
- 动态令牌:仅限本人持有的设备内显示的一次性密码
- 数字证书:仅限本人(终端)持有的信息
- 生物认证:指纹和虹膜等本人生理信息
- 身份证号、手机号等:仅限本人持有的信息
1. Basic 认证
Basic 身份认证,是 HTTP 1.0 中引入的认证方案之一。虽然方案比较古老,实现简单,同时存在安全缺陷。通过核对用户名、密码的方式,来实现用户身份的验证。
核心概念
- Userid
- Password
- Realm:认证保护域,其实就是指当前认证的保护范围
关于realm:同一个 server,访问受限的资源多种多样,比如资金信息、机密文档等。可以针对不同的资源定义不同的 realm,并且只允许特定的用户访问。跟Linux下的账户、分组体系很像。
认证流程
在进行 BASIC 认证的过程中,HTTP 的请求头字段会包含 Authorization 字段,Authorization: Basic <用户凭证>
,该<用户凭证>是 userid 和 password 的组合而成的 Base64 编码。
GET /securefiles/ HTTP/1.1
Host: www.example.com
Authorization: Basic aHR0cHdhdGNoOmY=
BASIC 认证流程图:
1. 用户在浏览器中访问了受限制的网页资源,但是没有提供用户的身份信息
2. 服务端接收到请求后返回 401 应答码(Unauthorized,未被授权的)要求进行身份验证,并附带提供了一个认证域(Access Authentication)WWW-Authenticate
说明如何进行验证的方法,例如 WWW-Authenticate: Basic realm="Secure Area"
,Basic
就是验证的模式,而 realm="Secure Area"
则为保护域(告知认证的范围),用于与其他请求 URI 作区别
3. 浏览器收到应答后,会显示该认证域给用户并提示输入用户名和密码,此时用户可以选择录入信息后确定或取消操作
4. 用户输入了用户名和密码后,浏览器会在原请求头新增认证消息字段 Authorization
并重新发送请求,过程如下:
- 将用户名和密码拼接为
用户名:密码
格式的字符串
- 将字符串编码为 Base64
- 拼接
Basic
,设置为Authorization
字段,假设用户名为admin
,密码为password
,则拼接后为admin:password
,使用 Base64 编码后为YWRtaW46cGFzc3dvcmQ=
,那么最终在 HTTP 头部里会是这样:
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
5. 服务端接收了该认证后并返回了用户请求的网页资源。如果用户凭证非法或无效,服务器可能会再次返回 401 应答码,客户端就需要再次输入用户名和密码
缺陷
Basic 认证的安全缺陷比较明显,它通过明文传输用户的密码,在 http 等非加密通信的线路上进行 Basic 认证的过程中如果被人监听,被盗的可能性极高。
除了安全缺陷,Basic 认证还存在无法吊销认证的情况。
2. Digest 认证
“摘要”式认证( Digest authentication)是一个简单的认证机制,最初是为HTTP协议开发的,因而也常叫做HTTP摘要,在 RFC2671 中描述。其身份验证机制很简单,它在密码发出前,先对其应用哈希函数,这相对于 HTTP Basic 认证发送明文而言,更安全。
Digest 认证同样使用质询/响应的方式(challenge/response),即一开始一方会先发送需要认证的请求给另一方,接着使用从另一方接收到的质询码计算生成响应码,最后将响应码返回给对方进行认证的方式。
参数介绍
- username:用户名
- realm:同上
- nonce:服务器发给客户端的随机的字符串,服务器每次产生一个摘要质询时,这个参数都是不一样的。nonce 通常是由一些数据通过 md5 运算构造的。这样的数据通常包括时间标识和服务器的机密短语。这确保每个 nonce 都有一个有限的生命期(也就是过了一些时间后会失效,并且以后再也不会使用),而且