Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ MFC&x2B;Wininet+;代理身份验证=问题_C++_Windows_Mfc_Wininet - Fatal编程技术网

C++ MFC&x2B;Wininet+;代理身份验证=问题

C++ MFC&x2B;Wininet+;代理身份验证=问题,c++,windows,mfc,wininet,C++,Windows,Mfc,Wininet,我有一些代码(实际上是通过web界面发送SMS消息,但这并不相关)。在没有代理服务器的情况下,代码可以正常工作,但有一个客户希望使用此配置。我一直在测试我们的代理,但无法让它工作。在阅读帮助时,我发现了MSKB文章195650(如何使用WinInet处理代理授权),其中包含以下智慧之珠: There are several ways to handle HTTP_STATUS_PROXY_AUTH_REQ without displaying a user interface. By far t

我有一些代码(实际上是通过web界面发送SMS消息,但这并不相关)。在没有代理服务器的情况下,代码可以正常工作,但有一个客户希望使用此配置。我一直在测试我们的代理,但无法让它工作。在阅读帮助时,我发现了MSKB文章195650(如何使用WinInet处理代理授权),其中包含以下智慧之珠:

There are several ways to handle HTTP_STATUS_PROXY_AUTH_REQ without
displaying a user interface. By far the easiest way to do this is by 
using the InternetSetOption function with the flags
INTERNET_OPTION_PROXY_PASSWORD and INTERNET_OPTION_PROXY_USERNAME...

...The same functionality can be accomplished in an MFC application 
by detecting HTTP_STATUS_PROXY_AUTH_REQ, calling 
CHttpConnection::SetOption, then re-calling CHttpFile::SendRequest. 
因此,我在代码中实现了这个解决方案,从需要身份验证的代理中检测到407错误,然后通过SetOption调用提供基本身份验证:

     if (AfxParseURL (m_csServerUrl, dwServiceType, csServerName, csObjectName, nPort))
     {
        CString csProxy = m_pOwner->GetProxyServerSetting();
        if (csProxy.GetLength() > 0)
        {
           pSession  = new CMyInternetSession (TEXT("SmGen"),
                                               1,
                                               INTERNET_OPEN_TYPE_PROXY,
                                               csProxy,
                                               NULL,
                                               INTERNET_FLAG_KEEP_CONNECTION);
        }
        else
        {
           pSession  = new CMyInternetSession (TEXT("SmGen"),
                                               1,
                                               INTERNET_OPEN_TYPE_PRECONFIG,
                                               NULL,
                                               NULL,
                                               0);
        }
        if (pSession)
        {
           pSession->SetOwnerDialog (m_pOwner);
           pHttpConn = pSession->GetHttpConnection (csServerName, (INTERNET_PORT)nPort, NULL, NULL);

           if (pHttpConn)
           {
              dwFlags = INTERNET_FLAG_RELOAD | 
                        INTERNET_FLAG_DONT_CACHE;    
              pHttpFile = pHttpConn->OpenRequest (CHttpConnection::HTTP_VERB_GET, 
                                                  csObjectName + TEXT("?") + csHTTP,
                                                  NULL,
                                                  1,
                                                  NULL,
                                                  NULL, 
                                                  dwFlags);
              if (pHttpFile)
              {
                 pHttpFile->AddRequestHeaders (csHeaders);

                 if (pHttpFile->SendRequest ())
                 {
                    pHttpFile->QueryInfoStatusCode (dwResult);
                    bRetryWithAuth = FALSE;

                    switch (dwResult)
                    {
                       case HTTP_STATUS_OK:
                          // log success
                          break;

                       case HTTP_STATUS_PROXY_AUTH_REQ:
                          bRetryWithAuth = TRUE;
                          break;

                       default:
                          // log failure
                          break;
                    }

                    if (bRetryWithAuth)
                    {
                       csProxyUsr = m_pOwner->GetProxyUsername();
                       csProxyPwd = m_pOwner->GetProxyPassword();

                       pHttpConn->SetOption (INTERNET_OPTION_PROXY_USERNAME,
                                             csProxyUsr.GetBuffer(1),
                                             csProxyUsr.GetLength());
                       csProxyUsr.ReleaseBuffer();

                       pHttpConn->SetOption (INTERNET_OPTION_PROXY_PASSWORD,
                                             csProxyPwd.GetBuffer(1),
                                             csProxyPwd.GetLength());
                       csProxyPwd.ReleaseBuffer();

                       if (pHttpFile->SendRequest ())
                       {
                          // ... TIMEOUT
现在来看问题。问题是第二个SendRequest没有失败或抛出另一个错误,它只是超时。过了一会儿,我通过包装器处理程序抛出CInternetException 12002(超时)。这有点烦人。不用说,短信永远不会到达

代理服务器地址的格式为a.b.c.d:8080,以消除DNS作为诱因。我的MIS部门向我保证,我提供的用户名和密码是有效的(如果我传递了一个错误的uid/pwd,它会简单地恢复为407错误,因此我知道他们正在访问代理,至少是这样)

我已经在这里和网上找到了所有我能找到的东西,但我一事无成。遗憾的是,仅仅使用INTERNET\u OPEN\u TYPE\u Prefig并希望系统能够自动获取所需的一切,如果您只有一个代理,那么这种方法是行不通的

请记住,代码中与代理无关的功能没有问题,因为如果我通过擦除提供服务器ip:端口的注册表项来消除代理,那么它将再次生效

我完全被难住了。以前有人见过这个吗?我不抱希望,因为有很多关于代理身份验证的问题没有得到答复

编辑:


我已将此代码转换为使用WinHttp,因为有一个MS示例包含代理(带有身份验证),而且WinInet无论如何都不推荐使用。现在一切正常。

通常在客户端收到响应后,HTTP连接关闭。 因此,当您发送第二个包含身份验证详细信息的请求时,代理将关闭连接(或至少停止接收)


因此,您必须再次调用OpenRequest以建立新连接。

如果您知道您正在访问代理。。。也许用Wireshark四处窥探会得到一些有用的信息?或者Fiddler?这与MSDN文档中说我只需重新发送的内容相矛盾,但这很容易尝试,所以我将在明天早上试一试并报告。HTTP连接在收到响应后不会关闭。如果这是真的,那将使网络通信速度大大降低。