以前做过http下载程序,现在要加上用户名密码验证的功能,看了http协议,有这样一些内容:
WWW-Authenticate  = "WWW-Authenticate" ":" 1#challenge,但是怎样运用却还没理出个头绪来,也没办法验证,因为我还没找到一个可以验证这个的需要用户名和密码的httpServer,不知有没有人遇到过这样的问题,望能告知一二,参考一下。

解决方案 »

  1.   

    ^_^,我也在做一个tcp的http1.1代理,遇到带验证(最简单的用户名密码)的问题,但是根据rfc2617发送的请求返回407错误,还没找到合适的解决办法,有机会一起交流
      

  2.   

    rfc2617-------->
    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授权方案往往存在许多不安全的地方。尽管如此,客户端仍然需要实现此方案,以
    与采用此种方案的服务器进行通讯。
      

  3.   

    谢谢,这个方面我也看过了相关的资料,只是还是无法和实际的联系起来,例如我现在用下面的方法来访问我自己的一个网页:
    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,我该怎么做呢?
    服务器端需要一些什么相应的设置,这个问题困扰我好久,也没看到什么具体的解决方法,一直在寻找控索中,望有知道的各位能帮帮忙。
      

  4.   

    我做了一个测试程序,是用微软的标准的API做的,根据说明,在GetHttpConnection中加上适当的参数即可,可我加上了用户名密码的参数,得到的发出去的包和没加上用户名密码所发出去的包居然是一样的,不知哪里出现了错误。
    以下是一段测试程序。
    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
      

  5.   

    为了接收授权,客户端需要在基于64位(base64 [5])的证书中发送用户标识及口令,
    中间用冒号':'分隔。
    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编码可以到网上找找,很多的
      

  6.   

    就是在你发送请求的时候插入一行Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
      

  7.   

    我用IIS配置了一个Web服务器,采用的是基本验证,然后对于网页所在的目录是NTFS格式的,这样,当登录网页时就会要求输入用户名密码,用抓包工具我发现如果用IE登录会得到如下的包(用户名:zhu,密码:123)
    第一次应答:
    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>
      

  8.   

    m_phttpFile->SendRequest();这里好像是有点问题的
    因为现在是需要用户输入用户名密码的登陆方式,所以这时SendRequest();应该是需要参数的。将你重新组的http头发出去
      

  9.   

    mana_(ke) 你还在吗?我把你的话反复看了好多遍,实际上就是最后插入一行Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    可是我试验还是通不过,你试过了吗?
    按照理论上说是应该能通过的。
    另外我发现将用浏览器登录抓下来的包进行base64解码,得到的很像是Unicode 字符,难不成是这个原因导致不成功。望有识之人指教。
    这个问题若弄明白了应是不难的,只是找不到任何成功的案例。
      

  10.   

    提供有关Base64的源码:
    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;

    有关基本授权找不到更进一步的资料了,
    想来这是目前网上最全的资料,都整理在这儿。
    暂时只有搁置,希望在不久的将来能搞定。