一. HTTP Basic
客户端以“ : ”连接用户名和密码后,再经BASE64加密通过Authorization请求头发送该密文至服务端进行验证,每次请求都需要重复发送该密文。可见Basic认证过程简单,安全性也低,存在泄露个人账号信息以及其他诸多安全问题。以下仅为原理演示,不代表真实情况:
- 客户端向服务器请求数据:
GET / HTTP/1.1
Host: www.myrealm.com - 服务端向客户端发送验证请求401:
HTTP/1.1 401 Unauthorised
Server: bfe/1.0.8.18
WWW-Authenticate: Basic realm="myrealm.com"
Content-Type: text/html; charset=utf-8 - 客户端收到401返回值后,将自动弹出一个登录窗口,等待用户输入用户名和密码
- 将“用户名:密码”进行BASE64加密后发送服务端进行验证:
GET / HTTP/1.1
Host: www.myrealm.com
Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx - 服务端取出Authorization请求头信息进行解密,并与用户数据库进行对比判断是否合法,合法将返回200 OK,至于是否发送Authentication-Info头部则是可选的
1 <?php 2 if (!isset($_SERVER[‘PHP_AUTH_USER‘])) { 3 header(‘WWW-Authenticate: Basic realm="My Realm"‘); 4 header(‘HTTP/1.0 401 Unauthorized‘); 5 echo ‘Text to send if user hits Cancel button‘; 6 exit; 7 } else { 8 echo "<p>Hello {$_SERVER[‘PHP_AUTH_USER‘]}.</p>"; 9 echo "<p>You entered {$_SERVER[‘PHP_AUTH_PW‘]} as your password.</p>"; 10 }
二. Digest 认证
Digest认证试图解决Basic认证的诸多缺陷而设计,用户密码在整个认证过程中是个关键性要素。
下为服务端发送的Digest认证头部实例及各字段含义说明:PHP官方文档中发送WWW-Authenticate头部时各字段之间用了空格,在Chrome下是不会弹出认证对话框的,应该换成”, “或”,“
WWW-Authenticate:Digest realm="Restricted area", qop="auth,auth-int", nonce="58e8e52922398", opaque="cdce8a5c95a1427d74df7acbf41c9ce0", algorithm="MD5"
- WWW-Authenticate:服务端发送的认证头部
- qop:质量保证,在摘要质询中用来告知客户端服务端支持的认证算法列表;在响应中其值可为auth或auth-int,auth-int包含对实体主体做完整性校验,qop未定义则默认为auth
- nonce:服务端产生的一次性随机数,用于服务端对客户端的确认,防止重放攻击。RFC2617建议采用这个随机数计算公式:nonce = BASE64(time-stamp MD5(time-stamp “:” ETag “:” private-key)),服务端可以决定这种nonce时间有效性,ETag(URL的Entity Tag,在cgi编程中通常需要自行生成ETag和鉴别,用于标示URL对象是否改变,区分不同语言、Session、Cookie等)可以防止对已更新资源版本(未更新无效,故需要考虑时间新鲜度)的重放请求,private-key为服务端私有
- opaque:这是一个不透明的(不让外人知道其意义)数据字符串,在盘问中发送给客户端,客户端会将这个数据字符串再发送回服务端器。如果需要在服务端和客户端之间维护一些状态,可以用这个参数传送状态给客户端。
- algorithm:摘要算法,目前支持只MD5
下为客户端发送的Digest认证头部实例及各字段含义说明:
Authorization:Digest username="somename", realm="Restricted area", nonce="58e8e52922398", uri="/t.php", response="9c839dde909d270bc5b901c7f80f77d5", opaque="cdce8a5c95a1427d74df7acbf41c9ce0", qop="auth", nc=00000001, cnonce="9c30405c3a67a259"
- cnonce:客户端产生的一次性随机数,用于客户端对服务器的确认
- nc:让服务端能够通过维护请求次数,检测到重复请求。如果相同的nc出现在两次请求中,那么这两次请求即为重复请求。所以对于防止重放攻击而言,除了nonce之外,nc才是最后的保证
- Authorization-Info:(略,此处包含nextnonce、rspauth响应摘要等)
下为算法说明:
- H(v1) = MD5(v1),将v1进行MD5编码
- KD(v1, v2) = MD5(v1 : v2),将v1和v2用冒号”:”连接后进行MD5编码
- A1表示包含安全信息的数据块,A1=(user):(realm):(password)
- QoP(保护质量),对不包含安全信息的数据设置保护方式,可选项:auth、auth-int
- A2表示不包含安全信息的数据块,根据qop值确定:
a) QoP=auth或undefined时,A2=(request-method) : (uri-directive-value) b) QoP=auth-int时,A2=(request-method) : (uri-directive-value) : H((entity-body))
- 老摘要算法:兼容RFC2069,在没有qop选项时使用
KD(H(A1), (nonce) : H(A2)) = MD5(MD5(A1) : (nonce) : MD5(A2)) = MD5(MD5((user) : (realm) : (password)) : (nonce) : MD5((request-method) : (uri-directive-value)))
- 新摘要算法:新摘要算法为推荐方式,包含了对随机数计算和对称认证的支持。只要qop为auth或auth-int,就要使用这种方式
KD(H(A1), (nonce) : (nc) : (cnonce) : (qop) : H(A2)) = MD5(MD5(A1) : (nonce) : (nc) : (cnonce) : (qop) : MD5(A2)) = MD5(MD5((user) : (realm) : (password)) : (nonce) : (nc) : (cnonce) : (qop) : MD5((request-method) : (uri-directive-value) : MD5((entity-body))))
时间: 2024-11-09 00:40:18