PHP作为客户端进行HTTP Digest校验
// 请求方法
$username = 'admin';
$password = 'admin123';
$uri = "api/cgi-bin/subscribe/picture";
$url = $this->url .$uri;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch,CURLOPT_TIMEOUT, 30);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch,CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HEADER, 1);
$first_response = curl_exec($ch);
$info = curl_getinfo($ch);
preg_match('/WWW-Authenticate: Digest (.*)/', $first_response, $matches);
preg_match('/Set-Cookie: (.*)/', $first_response, $SessionIDmatches);
if(!empty($matches))
{
$auth_header = $matches[1];
$auth_header_array = explode(',', $auth_header);
$parsed = array();
foreach ($auth_header_array as $pair)
{
$vals = explode('=', $pair);
$parsed[trim($vals[0])] = trim($vals[1], '" ');
}
$cnonce = rand(1000000000000000,9999999999999999);
$nc = 00000001;
$response_realm = (isset($parsed['realm'])) ? $parsed['realm'] : "";
$response_nonce = (isset($parsed['nonce'])) ? $parsed['nonce'] : "";
$response_opaque = (isset($parsed['opaque'])) ? $parsed['opaque'] : "";
$authenticate1 = md5($username.":".$response_realm.":".$password);
$authenticate2 = md5("POST:".$url);
$authenticate_response = md5($authenticate1.":".$response_nonce.":".$nc.":".$cnonce.":".$parsed['qop'].":".$authenticate2);
$request = sprintf('Authorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s", qop="%s", nc="%s", cnonce="%s"',
$username, $response_realm, $response_nonce, $url, $authenticate_response,$parsed['qop'],$nc,$cnonce);
$requestcookie = 'Cookie: '.$SessionIDmatches['1'];
$request_header = array($request,$requestcookie);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch,CURLOPT_TIMEOUT, 30);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch,CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_header);
$result['response'] = curl_exec($ch);
$result['info'] = curl_getinfo ($ch);
$result['info']['errno'] = curl_errno($ch);
$result['info']['errmsg'] = curl_error($ch);
}
当客户端发起任意接口访问请求与设备建立会话时,设备会检查session是否有效(进行过digest校验并校验未失效的session为有效的session),设备只会对session有效客户端正常响应.
当客户端发起访问的session无效时,
设备返回401链接状态.
WWW-Authenticate字段返回校验用的参数.
Set-Cookie字段返回新的session.
当客户端检测到401链接状态,读取http头中的校验信息进行digest校验的计算
获得在WWW-Authenticate字段中附带的realm,qop,nonce,opaque等参数
集合客户端的username,password,cnonce,nc等参数
按照qop计算校验码(在本系统的校验中qop的值为auth,所以按照如下方式计算)
A1 = username:realm:password
A2 = mthod:uri
HA1 = MD5(A1)
HA2 = MD5(A2)
response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
计算出response之后,再一次发起访问的请求,在Authorization中添加校验相关参数与和返回中获取的Cookie发送到设备
设备会根据收到的校验信息,与使用存在设备当中的密码计算出的校验码比较,来确认客户的身份(账号密码)是否正确,校对通过则开始正常通信