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
一个无符号整数,指定包含支持的身份验证方案的标志。 此参数可以返回下表中标识的一个或多个标志。
[out] lpdwFirstScheme
一个无符号整数,指定包含服务器列出的第一个身份验证方案的标志。 此参数可以返回下表中标识的一个或多个标志。
[out] pdwAuthTarget
一个无符号整数,指定包含身份验证目标的标志。 此参数可以返回下表中标识的一个或多个标志。
值 | 含义 |
---|---|
|
身份验证目标是服务器。 指示已收到 401 状态代码。 |
|
身份验证目标是代理。 指示已收到 407 状态代码。 |
返回值
如果成功,则返回 TRUE ;如果失败,则返回 FALSE 。 要获得更多的错误信息,请调用 GetLastError。 下表标识了返回的错误代码。
错误代码 | 说明 |
---|---|
|
此操作提供的句柄类型不正确。 |
|
发生了内部错误。 |
|
内存不足,无法完成请求的操作。 (Windows 错误代码) |
注解
即使在异步模式下使用 WinHTTP, (即在 WinHttpOpen) 中设置WINHTTP_FLAG_ASYNC时,此函数也会同步运行。 返回值指示成功或失败。 要获得更多的错误信息,请调用 GetLastError。
在调用 WinHttpQueryHeaders 之前,无法使用 WinHttpQueryAuthSchemes。
注意 对于 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 Professional SP3 [仅限桌面应用] |
最低受支持的服务器 | Windows Server 2003、Windows 2000 Server SP3 [仅限桌面应用] |
目标平台 | Windows |
标头 | winhttp.h |
Library | Winhttp.lib |
DLL | Winhttp.dll |
可再发行组件 | Windows XP 和 Windows 2000 上的 WinHTTP 5.0 和 Internet Explorer 5.01 或更高版本。 |