上一编中讲到了HTTP的基本认证,本文继续讲述HTTP的另外一种认证方式-摘要认证。
认证的过程依然是分为4个步骤,只是细节有些区别。
1. 用户请求受保护的资源,例如:
- GET http://192.168.2.1/ HTTP/1.1
- Accept: text/html, application/xhtml+xml, */*
- Accept-Language: zh-CN
- User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
- Accept-Encoding: gzip, deflate
- Connection: Keep-Alive
- Host: 192.168.2.1
2. 服务端返回401未认证的错误
3. 加入用户信息,重新发送请求
- HTTP/1.1 401 Unauthorized
- Content-Type: text/html; charset=GB2312
- Date: Wed, 28 Aug 2013 19:28:03 GMT
- Last-Modified: Wed, 28 Aug 2013 19:28:03 GMT
- Accept-Ranges: bytes
- Connection: close
- Cache-Control: no-cache,no-store
- WWW-Authenticate: Digest realm="abcdalom.com", nonce="0123456789abcdef"
- <HTML>
- <HEAD><TITLE>401 Unauthorized</TITLE></HEAD>
- <BODY BGCOLOR="#FFFFFF" TEXT="#483D8B" LINK="#2020ff" VLINK="#4040cc">
- <H2>401 Unauthorized</H2>
401错误的HTTP头部中都会带有WWW-Authenticate字段,其中指明了服务端支持的认证方式,一般为Basic(基本认证)和 Digest(摘要认证)两种可选值。在上文的回应中可见,服务端支持的认证方式为摘要认证。在WWW-Authenticate字段中,除了指明使用摘要认证外,还包括了realm和nonce(随机字符串)。
4. 服务端验证用户信息是否合法,如果合法请返回用户请求的资源。否则依然回应401的错误。需要在HTTP头部中加入Authorization字段,并显示指明认证方式(认证方式可由第2步获取)。摘要信息的计算如下所示:
static int digest_compute(Authentication_t *auth) { char *elem[3], ha1[33], ha2[33]; char dst[128]; printf("nonce:%s.\r\n",auth->nonce); printf("realm:%s.\r\n",auth->realm); printf("uri:%s.\r\n",auth->url); printf("method:%s.\r\n",auth->method); // MD5(username:realm:password) , USERINFODIGEST elem[0] = auth->user; elem[1] = auth->realm; elem[2] = AUTH_DEFAULT_PWD; md5_hash( elem, 3, ha1 ); // MD5(method:url) , MURLDIGEST elem[0] = auth->method; elem[1] = auth->url; md5_hash( elem, 2, ha2 ); // MD5(USERINFODIGEST:nonce:MURLDIGEST) elem[0] = ha1; elem[1] = auth->nonce; elem[2] = ha2; md5_hash( elem, 3, dst); printf("Digest response: %s\n",dst); return TRUE; }
注:realm和nonce必须使用第2步中获取到的值,method方法要根据实际中使用HTTP方法,例如下面的HTTP请求,采用的方法为“GET"
- GET http://192.168.2.1/ HTTP/1.1
- Accept: text/html, application/xhtml+xml, */*
- Accept-Language: zh-CN
- User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
- Accept-Encoding: gzip, deflate
- Connection: Keep-Alive
- Authorization: Digest username="admin", realm="abcdalom.com", nonce="0123456789abcdef", uri="http://192.168.2.1/", response="xfdsfji32309jfkfsd8923jfjsdif3jdsf"
- Host: 192.168.2.1