Función WinHttpQueryAuthSchemes (winhttp.h)

La función WinHttpQueryAuthSchemes devuelve los esquemas de autorización admitidos por el servidor.

Sintaxis

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

Parámetros

[in] hRequest

Identificador HINTERNET válido devuelto por WinHttpOpenRequest

[out] lpdwSupportedSchemes

Entero sin signo que especifica una marca que contiene los esquemas de autenticación admitidos. Este parámetro puede devolver una o varias marcas que se identifican en la tabla siguiente.

Value Significado
WINHTTP_AUTH_SCHEME_BASIC
Indica que la autenticación básica está disponible.
WINHTTP_AUTH_SCHEME_NTLM
Indica que la autenticación NTLM está disponible.
WINHTTP_AUTH_SCHEME_PASSPORT
Indica que la autenticación de passport está disponible.
WINHTTP_AUTH_SCHEME_DIGEST
Indica que la autenticación implícita está disponible.
WINHTTP_AUTH_SCHEME_NEGOTIATE
Selecciona entre la autenticación NTLM y Kerberos.

[out] lpdwFirstScheme

Entero sin signo que especifica una marca que contiene el primer esquema de autenticación enumerado por el servidor. Este parámetro puede devolver una o varias marcas que se identifican en la tabla siguiente.

Value Significado
WINHTTP_AUTH_SCHEME_BASIC
Indica que la autenticación básica es la primera.
WINHTTP_AUTH_SCHEME_NTLM
Indica que la autenticación NTLM es la primera.
WINHTTP_AUTH_SCHEME_PASSPORT
Indica que la autenticación de passport es la primera.
WINHTTP_AUTH_SCHEME_DIGEST
Indica que la autenticación implícita es la primera.
WINHTTP_AUTH_SCHEME_NEGOTIATE
Selecciona entre la autenticación NTLM y Kerberos.

[out] pdwAuthTarget

Entero sin signo que especifica una marca que contiene el destino de autenticación. Este parámetro puede devolver una o varias marcas que se identifican en la tabla siguiente.

Value Significado
WINHTTP_AUTH_TARGET_SERVER
El destino de autenticación es un servidor. Indica que se ha recibido un código de estado 401.
WINHTTP_AUTH_TARGET_PROXY
El destino de autenticación es un proxy. Indica que se ha recibido un código de estado 407.

Valor devuelto

Devuelve TRUE si es correcto o FALSE si no se realiza correctamente. Para obtener información de error extendida, llame a GetLastError. En la tabla siguiente se identifican los códigos de error que se devuelven.

Código de error Descripción
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
El tipo de identificador proporcionado es incorrecto para esta operación.
ERROR_WINHTTP_INTERNAL_ERROR
Se ha producido un error interno.
ERROR_NOT_ENOUGH_MEMORY
No había suficiente memoria disponible para completar la operación solicitada. (Código de error de Windows)

Comentarios

Incluso cuando WinHTTP se usa en modo asincrónico (es decir, cuando WINHTTP_FLAG_ASYNC se establece en WinHttpOpen), esta función funciona de forma sincrónica. El valor devuelto indica éxito o error. Para obtener información de error extendida, llame a GetLastError.

No se puede usar WinHttpQueryAuthSchemes antes de llamar a WinHttpQueryHeaders.

Nota Para Windows XP y Windows 2000, consulta la sección Requisitos en tiempo de ejecución de la página de inicio de WinHttp.
 

Ejemplos

En el ejemplo siguiente se muestra cómo recuperar un documento especificado de un servidor HTTP cuando se requiere autenticación. El código de estado se recupera de la respuesta para determinar si el servidor o el proxy solicitan autenticación. Si se encuentra un código de estado 200, el documento está disponible. Si se encuentra un código de estado 401 o 407, se requiere autenticación antes de que se pueda recuperar el documento. Para cualquier otro código de estado, se muestra un mensaje de error.

#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 );
}


Requisitos

   
Cliente mínimo compatible Windows XP, Windows 2000 Professional con SP3 [solo aplicaciones de escritorio]
Servidor mínimo compatible Windows Server 2003, Windows 2000 Server con SP3 [solo aplicaciones de escritorio]
Plataforma de destino Windows
Encabezado winhttp.h
Library Winhttp.lib
Archivo DLL Winhttp.dll
Redistribuible WinHTTP 5.0 e Internet Explorer 5.01 o posterior en Windows XP y Windows 2000.

Consulte también

Acerca de los servicios HTTP de Microsoft Windows (WinHTTP)

Versiones de WinHTTP

WinHttpSetCredentials