WinHttpQueryAuthSchemes 函式 (winHTTP.h)

WinHttpQueryAuthSchemes函式會傳回伺服器支援的授權配置。

語法

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

參數

[in] hRequest

WinHttpOpenRequest傳回的有效HINTERNET控制碼

[out] lpdwSupportedSchemes

不帶正負號的整數,指定包含支援之驗證配置的旗標。 此參數可以傳回下表中所識別的一或多個旗標。

意義
WINHTTP_AUTH_SCHEME_BASIC
表示基本驗證可供使用。
WINHTTP_AUTH_SCHEME_NTLM
表示 NTLM 驗證可供使用。
WINHTTP_AUTH_SCHEME_PASSPORT
表示 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
表示 Passport 驗證是第一個。
WINHTTP_AUTH_SCHEME_DIGEST
表示摘要式驗證是第一個。
WINHTTP_AUTH_SCHEME_NEGOTIATE
選取 NTLM 與 Kerberos 驗證。

[out] pdwAuthTarget

不帶正負號的整數,指定包含驗證目標的旗標。 此參數可以傳回下表中所識別的一或多個旗標。

意義
WINHTTP_AUTH_TARGET_SERVER
驗證目標為伺服器。 表示已收到 401 狀態碼。
WINHTTP_AUTH_TARGET_PROXY
驗證目標為 Proxy。 表示已收到 407 狀態碼。

傳回值

如果成功,則傳回 TRUE ,如果失敗則傳回 FALSE 。 若要取得擴充的錯誤資訊,請呼叫 GetLastError。 下表識別傳回的錯誤碼。

錯誤碼 描述
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
針對此作業提供的控制碼類型不正確。
ERROR_WINHTTP_INTERNAL_ERROR
發生內部錯誤。
ERROR_NOT_ENOUGH_MEMORY
記憶體不足,無法完成要求的作業。 (Windows 錯誤碼)

備註

即使 WinHTTP 用於非同步模式 (亦即,在WinHttpOpen) 中設定WINHTTP_FLAG_ASYNC時,此函式仍會同步運作。 傳回值表示成功或失敗。 若要取得擴充的錯誤資訊,請呼叫 GetLastError

呼叫WinHttpQueryHeaders之前,無法使用WinHttpQueryAuthSchemes

注意 針對 Windows XP 和 Windows 2000,請參閱 WinHttp 起始頁面的 執行時間需求 一節。
 

範例

下列範例示範如何在需要驗證時,從 HTTP 伺服器擷取指定的檔。 狀態碼是從回應中擷取,以判斷伺服器或 Proxy 是否要求驗證。 如果找到 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 Professional 與 SP3 [僅限傳統型應用程式]
最低支援的伺服器 Windows Server 2003、Windows 2000 Server 與 SP3 [僅限桌面應用程式]
目標平台 Windows
標頭 winHTTP.h
程式庫 WinHTTP.lib
Dll Winhttp.dll
可轉散發套件 Windows XP 和 Windows 2000 上的 WinHTTP 5.0 和 Internet Explorer 5.01 或更新版本。

另請參閱

關於 Microsoft Windows HTTP Services (WinHTTP)

WinHTTP 版本

WinHttpSetCredentials