Поделиться через


Функция WinHttpQueryAuthSchemes (winhttp.h)

Функция WinHttpQueryAuthSchemes возвращает схемы авторизации, поддерживаемые сервером.

Синтаксис

WINHTTPAPI BOOL WinHttpQueryAuthSchemes(
  [in]  HINTERNET hRequest,
  [out] LPDWORD   lpdwSupportedSchemes,
  [out] LPDWORD   lpdwFirstScheme,
  [out] LPDWORD   pdwAuthTarget
);

Параметры

[in] hRequest

Допустимый дескриптор HINTERNET, возвращенный WinHttpOpenRequest

[out] lpdwSupportedSchemes

Целое число без знака, указывающее флаг, содержащий поддерживаемые схемы проверки подлинности. Этот параметр может возвращать один или несколько флагов, указанных в следующей таблице.

Значение Значение
WINHTTP_AUTH_SCHEME_BASIC
Указывает, что доступна обычная проверка подлинности.
WINHTTP_AUTH_SCHEME_NTLM
Указывает, что проверка подлинности NTLM доступна.
WINHTTP_AUTH_SCHEME_PASSPORT
Указывает, что доступна проверка подлинности по паспорту.
WINHTTP_AUTH_SCHEME_DIGEST
Указывает, что доступна дайджест-проверка подлинности.
WINHTTP_AUTH_SCHEME_NEGOTIATE
Выбирает между проверками подлинности NTLM и Kerberos.

[out] lpdwFirstScheme

Целое число без знака, указывающее флаг, содержащий первую схему проверки подлинности, указанную сервером. Этот параметр может возвращать один или несколько флагов, указанных в следующей таблице.

Значение Значение
WINHTTP_AUTH_SCHEME_BASIC
Указывает, что в первую очередь используется обычная проверка подлинности.
WINHTTP_AUTH_SCHEME_NTLM
Указывает, что проверка подлинности NTLM выполняется в первую очередь.
WINHTTP_AUTH_SCHEME_PASSPORT
Указывает, что проверка подлинности по паспорту выполняется в первую очередь.
WINHTTP_AUTH_SCHEME_DIGEST
Указывает, что сначала выполняется дайджест-проверка подлинности.
WINHTTP_AUTH_SCHEME_NEGOTIATE
Выбирает между проверками подлинности NTLM и Kerberos.

[out] pdwAuthTarget

Целое число без знака, указывающее флаг, содержащий целевой объект проверки подлинности. Этот параметр может возвращать один или несколько флагов, указанных в следующей таблице.

Значение Значение
WINHTTP_AUTH_TARGET_SERVER
Целевым объектом проверки подлинности является сервер. Указывает, что получен код состояния 401.
WINHTTP_AUTH_TARGET_PROXY
Целевым объектом проверки подлинности является прокси-сервер. Указывает, что получен код состояния 407.

Возвращаемое значение

Возвращает значение TRUE в случае успешного выполнения или ЗНАЧЕНИЕ FALSE в случае неудачи. Дополнительные сведения об ошибке можно получить, вызвав GetLastError. В следующей таблице указаны коды ошибок, которые возвращаются.

Код ошибки Описание
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
Для этой операции указан неправильный тип дескриптора.
ERROR_WINHTTP_INTERNAL_ERROR
Произошла внутренняя ошибка.
ERROR_NOT_ENOUGH_MEMORY
Недостаточно памяти для выполнения запрошенной операции. (Код ошибки Windows)

Комментарии

Даже если WinHTTP используется в асинхронном режиме (то есть при установке WINHTTP_FLAG_ASYNC в WinHttpOpen), эта функция работает синхронно. Возвращаемое значение указывает на успех или сбой. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.

WinHttpQueryAuthSchemes нельзя использовать перед вызовом WinHttpQueryHeaders.

Примечание Для Windows XP и Windows 2000 см. раздел Требования во время выполнения начальной страницы WinHttp.
 

Примеры

В следующем примере показано, как получить указанный документ с HTTP-сервера, когда требуется проверка подлинности. Код состояния извлекается из ответа, чтобы определить, запрашивает ли сервер или прокси-сервер проверку подлинности. Если найден код состояния 200, документ доступен. Если найден код состояния 401 или 407, перед извлечением документа требуется проверка подлинности. Для любого другого кода состояния отображается сообщение об ошибке.

#include <windows.h>
#include <winhttp.h>
#include <stdio.h>

#pragma comment(lib, "winhttp.lib")

DWORD ChooseAuthScheme( DWORD dwSupportedSchemes )
{
  //  It is the server's responsibility only to accept 
  //  authentication schemes that provide a sufficient level
  //  of security to protect the server's resources.
  //
  //  The client is also obligated only to use an authentication
  //  scheme that adequately protects its username and password.
  //
  //  Thus, this sample code does not use Basic authentication  
  //  because Basic authentication exposes the client's username 
  //  and password to anyone monitoring the connection.
  
  if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE )
    return WINHTTP_AUTH_SCHEME_NEGOTIATE;
  else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM )
    return WINHTTP_AUTH_SCHEME_NTLM;
  else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_PASSPORT )
    return WINHTTP_AUTH_SCHEME_PASSPORT;
  else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_DIGEST )
    return WINHTTP_AUTH_SCHEME_DIGEST;
  else
    return 0;
}

struct SWinHttpSampleGet
{
  LPCWSTR szServer;
  LPCWSTR szPath;
  BOOL fUseSSL;
  LPCWSTR szServerUsername;
  LPCWSTR szServerPassword;
  LPCWSTR szProxyUsername;
  LPCWSTR szProxyPassword;
};

void WinHttpAuthSample( IN SWinHttpSampleGet *pGetRequest )
{
  DWORD dwStatusCode = 0;
  DWORD dwSupportedSchemes;
  DWORD dwFirstScheme;
  DWORD dwSelectedScheme;
  DWORD dwTarget;
  DWORD dwLastStatus = 0;
  DWORD dwSize = sizeof(DWORD);
  BOOL  bResults = FALSE;
  BOOL  bDone = FALSE;

  DWORD dwProxyAuthScheme = 0;
  HINTERNET  hSession = NULL, 
             hConnect = NULL,
             hRequest = NULL;

  // Use WinHttpOpen to obtain a session handle.
  hSession = WinHttpOpen( L"WinHTTP Example/1.0",  
                          WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                          WINHTTP_NO_PROXY_NAME, 
                          WINHTTP_NO_PROXY_BYPASS, 0 );

  INTERNET_PORT nPort = ( pGetRequest->fUseSSL ) ? 
                        INTERNET_DEFAULT_HTTPS_PORT  :
                        INTERNET_DEFAULT_HTTP_PORT;

  // Specify an HTTP server.
  if( hSession )
    hConnect = WinHttpConnect( hSession, 
                               pGetRequest->szServer, 
                               nPort, 0 );

  // Create an HTTP request handle.
  if( hConnect )
    hRequest = WinHttpOpenRequest( hConnect, 
                                   L"GET", 
                                   pGetRequest->szPath,
                                   NULL, 
                                   WINHTTP_NO_REFERER, 
                                   WINHTTP_DEFAULT_ACCEPT_TYPES,
                                   ( pGetRequest->fUseSSL ) ? 
                                       WINHTTP_FLAG_SECURE : 0 );

  // Continue to send a request until status code is not 401 or 407.
  if( hRequest == NULL )
    bDone = TRUE;

  while( !bDone )
  {
    //  If a proxy authentication challenge was responded to, reset 
    //  those credentials before each SendRequest, because the proxy  
    //  may require re-authentication after responding to a 401 or to 
    //  a redirect. If you don't, you can get into a 407-401-407-401
    //  loop.
    if( dwProxyAuthScheme != 0 )
      bResults = WinHttpSetCredentials( hRequest, 
                                        WINHTTP_AUTH_TARGET_PROXY, 
                                        dwProxyAuthScheme, 
                                        pGetRequest->szProxyUsername,
                                        pGetRequest->szProxyPassword,
                                        NULL );
    // Send a request.
    bResults = WinHttpSendRequest( hRequest,
                                   WINHTTP_NO_ADDITIONAL_HEADERS,
                                   0,
                                   WINHTTP_NO_REQUEST_DATA,
                                   0, 
                                   0, 
                                   0 );

    // End the request.
    if( bResults )
      bResults = WinHttpReceiveResponse( hRequest, NULL );

    // Resend the request in case of 
    // ERROR_WINHTTP_RESEND_REQUEST error.
    if( !bResults && GetLastError( ) == ERROR_WINHTTP_RESEND_REQUEST)
        continue;

    // Check the status code.
    if( bResults ) 
      bResults = WinHttpQueryHeaders( hRequest, 
                                      WINHTTP_QUERY_STATUS_CODE | 
                                          WINHTTP_QUERY_FLAG_NUMBER,
                                      NULL, 
                                      &dwStatusCode, 
                                      &dwSize, 
                                      NULL );

    if( bResults )
    {
      switch( dwStatusCode )
      {
        case 200: 
          // The resource was successfully retrieved.
          // You can use WinHttpReadData to read the contents 
          // of the server's response.
          printf( "The resource was successfully retrieved.\n" );
          bDone = TRUE;
          break;

        case 401:
          // The server requires authentication.
          printf(
           "The server requires authentication. Sending credentials\n");

          // Obtain the supported and preferred schemes.
          bResults = WinHttpQueryAuthSchemes( hRequest, 
                                              &dwSupportedSchemes, 
                                              &dwFirstScheme, 
                                              &dwTarget );

          // Set the credentials before re-sending the request.
          if( bResults )
          {
            dwSelectedScheme = ChooseAuthScheme( dwSupportedSchemes );

            if( dwSelectedScheme == 0 )
              bDone = TRUE;
            else
              bResults = WinHttpSetCredentials( 
                                        hRequest, dwTarget, 
                                        dwSelectedScheme,
                                        pGetRequest->szServerUsername,
                                        pGetRequest->szServerPassword,
                                        NULL );
          }

          // If the same credentials are requested twice, abort the
          // request.  For simplicity, this sample does not check for
          // a repeated sequence of status codes.
          if( dwLastStatus == 401 )
            bDone = TRUE;

          break;

        case 407:
          // The proxy requires authentication.
          printf( 
           "The proxy requires authentication. Sending credentials\n");

          // Obtain the supported and preferred schemes.
          bResults = WinHttpQueryAuthSchemes( hRequest, 
                                              &dwSupportedSchemes, 
                                              &dwFirstScheme, 
                                              &dwTarget );

          // Set the credentials before re-sending the request.
          if( bResults )
            dwProxyAuthScheme = ChooseAuthScheme(dwSupportedSchemes);

          // If the same credentials are requested twice, abort the
          // request.  For simplicity, this sample does not check for
          // a repeated sequence of status codes.
          if( dwLastStatus == 407 )
            bDone = TRUE;
          break;

        default:
          // The status code does not indicate success.
          printf( "Error. Status code %d returned.\n", dwStatusCode );
          bDone = TRUE;
      }
    }

    // Keep track of the last status code.
    dwLastStatus = dwStatusCode;

    // If there are any errors, break out of the loop.
    if( !bResults ) 
        bDone = TRUE;
  }

  // Report any errors.
  if( !bResults )
  {
    DWORD dwLastError = GetLastError( );
    printf( "Error %d has occurred.\n", dwLastError );
  }

  // Close any open handles.
  if( hRequest ) WinHttpCloseHandle( hRequest );
  if( hConnect ) WinHttpCloseHandle( hConnect );
  if( hSession ) WinHttpCloseHandle( hSession );
}


Требования

   
Минимальная версия клиента Windows XP, Windows 2000 Профессиональная с пакетом обновления 3 (SP3) [только классические приложения]
Минимальная версия сервера Windows Server 2003, Windows 2000 Server с пакетом обновления 3 (SP3) [только классические приложения]
Целевая платформа Windows
Header winhttp.h
Библиотека Winhttp.lib
DLL Winhttp.dll
Распространяемые компоненты WinHTTP 5.0 и Internet Обозреватель 5.01 или более поздней версии в Windows XP и Windows 2000.

См. также раздел

Сведения о службах HTTP Microsoft Windows (WinHTTP)

Версии WinHTTP

WinHttpSetCredentials