以前做过http下载程序,现在要加上用户名密码验证的功能,看了http协议,有这样一些内容:
WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge,但是怎样运用却还没理出个头绪来,也没办法验证,因为我还没找到一个可以验证这个的需要用户名和密码的httpServer,不知有没有人遇到过这样的问题,望能告知一二,参考一下。
WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge,但是怎样运用却还没理出个头绪来,也没办法验证,因为我还没找到一个可以验证这个的需要用户名和密码的httpServer,不知有没有人遇到过这样的问题,望能告知一二,参考一下。
11.1 基本授权方案(Basic Authentication Scheme)
用户代理必须对于每个领域(realm)通过用户标识(user-ID)及口令来对自身进行授
权,这是基本授权方案的工作模式。Realm值应当被看作不透明的字符串,该值将用于同服
务器端其它的realm值相比较。只有用户标识及口令通过受保护资源的认证,服务器才会给
请求授权。授权参数没有可选项。
在接收到对受保护区域的未经认证的资源请求时,服务器应当回应一个质询
(challenge),如下:WWW-Authenticate: Basic realm="WallyWorld""WallyWorld"是由服务器分配的字符串,用于对请求URI所指定的受保护资源进行标
识。
为了接收授权,客户端需要在基于64位(base64 [5])的证书中发送用户标识及口令,
中间用冒号':'分隔。basic-credentials = "Basic" SP basic-cookiebasic-cookie = <base64 [5] encoding of userid-password,
except not limited to 76 char/line>userid-password = [ token ] ":" *TEXT
如果用户代理希望发送用户标识"Aladdin"和口令“open sesame”,应当遵循下面的标题
域形式:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Basic授权方案是对HTTP服务器资源的非授权访问进行过滤的非安全方法。它基于假
定客户端与服务器端的连接是安全的,为什么说是假定呢,因为在实际的开放性网络中,使
用basic授权方案往往存在许多不安全的地方。尽管如此,客户端仍然需要实现此方案,以
与采用此种方案的服务器进行通讯。
GET /postinfo.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-icq, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: 192.168.1.175
Connection: Keep-Alive
然后我要加上用户名密码,假设用户名为:luhouxiang,密码为:123456,我该怎么做呢?
服务器端需要一些什么相应的设置,这个问题困扰我好久,也没看到什么具体的解决方法,一直在寻找控索中,望有知道的各位能帮帮忙。
以下是一段测试程序。
CInternetSession m_cis;
CHttpConnection *m_pHttpConnection;
CHttpFile *m_phttpFile; m_cis.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT,5);
m_pHttpConnection=m_cis.GetHttpConnection("192.168.1.175",(DWORD)80,INTERNET_INVALID_PORT_NUMBER,\
"luhouxiang","123456"); DWORD dwHttpRequestFlags =HSR_DOWNLOAD \
| INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT;
CString strStatus;
CString filename = "index.htm";
m_phttpFile = m_pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET,
filename, NULL, 1, NULL, NULL, dwHttpRequestFlags);
try
{
m_phttpFile->SendRequest();
}
catch(CInternetException* ex)
{
strStatus="连接服务器失败!";
m_phttpFile->Close();
ex->Delete();
return;
}
DWORD dwStatusCode;
m_phttpFile->QueryInfoStatusCode(dwStatusCode);
if(!((dwStatusCode>=200)&&(dwStatusCode<=299)))
{
strStatus= "连接失败!";
return ;
}
char buf[MAX_PATH];
CFile csf(filename,CFile::modeCreate|CFile::modeWrite);
while(1)
{
int n=m_phttpFile->Read(buf,MAX_PATH);
if(n<=0)
break;
csf.Write(buf,n);
}
csf.Close();
m_phttpFile->Close();发出来的包都是:
GET /index.htm HTTP/1.1
If-Modified-Since: Fri, 09 Dec 2005 08:00:02 GMT
If-None-Match: "b6681a8f96fcc51:d68"
User-Agent: TestHttpConnection
Host: 192.168.1.175
中间用冒号':'分隔。
basic-credentials = "Basic" SP basic-cookie
basic-cookie = <base64 [5] encoding of userid-password,
except not limited to 76 char/line>
userid-password = [ token ] ":" *TEXT
如果用户代理希望发送用户标识"Aladdin"和口令“open sesame”,应当遵循下面的标题
域形式:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
-------------------------------------------------
比如你用户名"Aladdin",密码“open sesame”,按照上面规则就应该发送的验证是
"Authorization: "basic-credentials
= "Authorization: Basic " + basic-cookie
= "Authorization: Basic " + basic-cookie
= "Authorization: Basic " + 基于base64编码的userid-password
= "Authorization: Basic " + 基于base64编码的userid-password
= "Authorization: Basic " + base64编码([ token ] ":" *TEXT)
= "Authorization: Basic " + base64编码([ "Aladdin" + ":" + "open sesame")
= "Authorization: Basic " + base64编码("Aladdin:open sesame")
= "Authorization: Basic " + "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
= "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="base64编码可以到网上找找,很多的
第一次应答:
GET /postinfo.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-icq, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
If-Modified-Since: Sat, 10 Dec 2005 07:32:52 GMT
If-None-Match: "1048f8ed5bfdc51:d6b"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: 192.168.0.175
Connection: Keep-AliveHTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.0
Date: Mon, 12 Dec 2005 03:05:56 GMT
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Connection: close
Content-Length: 3734
Content-Type: text/html
第二次应答:
GET /postinfo.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-icq, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
If-Modified-Since: Sat, 10 Dec 2005 07:32:52 GMT
If-None-Match: "1048f8ed5bfdc51:d6b"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: 192.168.0.175
Connection: Keep-Alive
Authorization: NTLM TlRMTVNTUAABAAAAB4IAogAAAAAAAAAAAAAAAAAAAAAFAJMIAAAAD2==
HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.0
Date: Mon, 12 Dec 2005 03:06:04 GMT
WWW-Authenticate: NTLM TlRMTVNTUAACAAAACAAIADgAAAAFgoKiLMM/bYc3JNgAAAAAAAAAADQANABAAAAABQCTCAAAAA9MAFUASQBTAAIACABMAFUASQBTAAEACABMAFUASQBTAAQACABsAHUAaQBzAAMACABsAHUAaQBzAAAAAAA=
Content-Length: 3728
Content-Type: text/html
第三次应答:
GET /postinfo.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-icq, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
If-Modified-Since: Sat, 10 Dec 2005 07:32:52 GMT
If-None-Match: "1048f8ed5bfdc51:d6b"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: 192.168.0.175
Connection: Keep-Alive
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAF4AAAAYABgAdgAAAAgACABIAAAABgAGAFAAAAAIAAgAVgAAAAAAAACOAAAABYKAogUAkwgAAAAPTABVAEkAUwB6AGgAdQBMAFUASQBTAMecmQ+QBunJ3FKI+mKAETooZDWUwiT+tOLuIpezuoH1CMqyQFkuDdscRiZdI+y9eA==HTTP/1.1 304 Not Modified
Server: Microsoft-IIS/5.0
Date: Mon, 12 Dec 2005 03:06:04 GMT
ETag: "1048f8ed5bfdc51:d6b"
Content-Length: 0最后结果是登录成功,转到相应的页面,可是我用这样的方法却是不行的,望有知情者指教:
GET postinfo.html HTTP/1.1
If-None-Match: "1048f8ed5bfdc51:d6b"
Host:192.168.0.175
Accept:*/*
User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)
Connection:Keep-Alive
Authorization: NTLM TlRMTVNTUAABAAAAB4IAogAAAAAAAAAAAAAAAAAAAAAFAJMIAAAAD2==
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAF4AAAAYABgAdgAAAAgACABIAAAABgAGAFAAAAAIAAgAVgAAAAAAAACOAAAABYKAogUAkwgAAAAPTABVAEkAUwB6AGgAdQBMAFUASQBTADBrI2LCY+8WaLzSFe8B++IEiAQrXMwmhkBPU1/TmNVnL9ibQdydKHU5qWHLffd1HW==
HTTP/1.1 400 Bad Request
Server: Microsoft-IIS/5.0
Date: Mon, 12 Dec 2005 03:26:20 GMT
Connection: close
Content-Type: text/html
Content-Length: 87<html><head><title>Error</title></head><body>The parameter is incorrect. </body></html>
因为现在是需要用户输入用户名密码的登陆方式,所以这时SendRequest();应该是需要参数的。将你重新组的http头发出去
可是我试验还是通不过,你试过了吗?
按照理论上说是应该能通过的。
另外我发现将用浏览器登录抓下来的包进行base64解码,得到的很像是Unicode 字符,难不成是这个原因导致不成功。望有识之人指教。
这个问题若弄明白了应是不难的,只是找不到任何成功的案例。
int Base64Enc(char *buf, char*text,int size)
{
static char *base64_encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int buflen = 0; while(size>0)
{
*buf++ = base64_encoding[ (text[0] >> 2 ) & 0x3f];
if(size>2)
{
*buf++ = base64_encoding[((text[0] & 3) << 4) | (text[1] >> 4)];
*buf++ = base64_encoding[((text[1] & 0xF) << 2) | (text[2] >> 6)];
*buf++ = base64_encoding[text[2] & 0x3F];
}
else
{
switch(size)
{
case 1:
{
*buf++ = base64_encoding[(text[0] & 3) << 4 ];
*buf++ = '=';
*buf++ = '=';
}
break;
case 2:
{
*buf++ = base64_encoding[((text[0] & 3) << 4) | (text[1] >> 4)];
*buf++ = base64_encoding[((text[1] & 0x0F) << 2) | (text[2] >> 6)];
*buf++ = '=';
}
break;
}
} text +=3;
size -=3;
buflen +=4;
} *buf = 0;
return buflen;
} //base64解码的实现char GetBase64Value(char ch)
{
if ((ch >= 'A') && (ch <= 'Z'))
return ch - 'A';
if ((ch >= 'a') && (ch <= 'z'))
return ch - 'a' + 26;
if ((ch >= '0') && (ch <= '9'))
return ch - '0' + 52;
switch (ch)
{
case '+':
return 62;
case '/':
return 63;
case '=': /* base64 padding */
return 0;
default:
return 0;
}
}//进行base64解码输入应该是4的倍数(根据mime标准)
//如果不是4倍数返回错误
//注意 如果是最后一个字符 那么长度不准备 可能会多1
//返回buf长度
int Base64Dec(char *Desbuf,char*Srctext,int size)
{
if(size%4)
return -1;
unsigned char chunk[4];
int parsenum=0; while(size>0)
{
chunk[0] = GetBase64Value(Srctext[0]);
chunk[1] = GetBase64Value(Srctext[1]);
chunk[2] = GetBase64Value(Srctext[2]);
chunk[3] = GetBase64Value(Srctext[3]); *Desbuf++ = (chunk[0] << 2) | (chunk[1] >> 4);
*Desbuf++ = (chunk[1] << 4) | (chunk[2] >> 2);
*Desbuf++ = (chunk[2] << 6) | (chunk[3]); Srctext+=4;
size-=4;
parsenum+=3;
} return parsenum;
}
有关基本授权找不到更进一步的资料了,
想来这是目前网上最全的资料,都整理在这儿。
暂时只有搁置,希望在不久的将来能搞定。