MFC + Wininet + проверка подлинности прокси = проблемы - PullRequest
3 голосов
/ 28 июля 2011

У меня есть некоторый код (на самом деле для отправки 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 (тайм-аут) через мой обработчик оболочки.Это немного раздражает.Само собой разумеется, что SMS никогда не приходит.

Адрес прокси-сервера имеет форму abcd: 8080 для устранения DNS как причинного фактора.Мой отдел MIS уверяет меня, что введенные мной имя пользователя и пароль действительны (если я передаю неверный uid / pwd, он просто возвращается к ошибке 407, так что я знаю, что они попадают на прокси-сервер, по крайней мере).

Я прошел через все, что я могу найти здесь и в Интернете, и я ничего не получаю.Простое использование INTERNET_OPEN_TYPE_PRECONFIG и надежда на то, что система автоматически получит все, что ей нужно, не работает, если, к сожалению, все, что у вас есть, - прокси.

Помните, что нет ничего плохого в функциональности кода, не связанной с проксипотому что, если я исключу прокси-сервер, протерев запись в реестре, содержащую ip: порт сервера, все это снова вступит в жизнь.

Я полностью в замешательстве.Кто-нибудь видел это раньше?Я не надеюсь, учитывая количество запросов о проверке подлинности прокси без ответов ...

Редактировать:

Я преобразовал этот код для использования WinHttp, так как есть пример MSкоторый покрывает прокси-сервер (с аутентификацией), а WinInet все равно не рекомендуется.Теперь все отлично работает.

1 Ответ

0 голосов
/ 30 июля 2011

Обычно HTTP-соединение закрывается после того, как клиент получил ответ. Таким образом, к моменту отправки вашего второго запроса с данными аутентификации прокси-сервер закроет соединение (или, по крайней мере, перестанет получать).

Так что вам придется снова вызывать OpenRequest, чтобы установить новое соединение.

...