Angeben von Serverauthentifizierungsanmeldeinformationen für einen BITS-Übertragungsauftrag
Sie können verschiedene Authentifizierungsschemas für einen BITS-Übertragungsauftrag (Background Intelligent Transfer Service) angeben.
Das folgende Verfahren ruft ein Authentifizierungsschema ab und erstellt eine Authentifizierungsidentitätsstruktur. Anschließend erstellt die Anwendung einen BITS-Downloadauftrag und legt die Anmeldeinformationen für den Auftrag fest. Nachdem der Auftrag erstellt wurde, erhält die Anwendung einen Zeiger auf eine Rückrufschnittstelle und ruft die status des BITS-Übertragungsauftrags ab. Nachdem der Auftrag abgeschlossen ist, wird er aus der Warteschlange entfernt.
In diesem Beispiel wird der Header und die Implementierung verwendet, die in Beispiel: Allgemeine Klassen definiert sind.
So geben Sie Anmeldeinformationen für die Serverauthentifizierung für einen BITS-Übertragungsauftrag an
Erstellen Sie eine Containerstruktur, die BG_AUTH_SCHEME-Werte Schemanamen zuordnet.
struct { LPCWSTR Name; BG_AUTH_SCHEME Scheme; } SchemeNames[] = { { L"basic", BG_AUTH_SCHEME_BASIC }, { L"digest", BG_AUTH_SCHEME_DIGEST }, { L"ntlm", BG_AUTH_SCHEME_NTLM }, { L"negotiate", BG_AUTH_SCHEME_NEGOTIATE }, { L"passport", BG_AUTH_SCHEME_PASSPORT }, { NULL, BG_AUTH_SCHEME_BASIC } };
Initialisieren Sie COM-Parameter, indem Sie die CCoInitializer-Funktion aufrufen. Weitere Informationen zur CCoInitializer-Funktion finden Sie unter Beispiel: Allgemeine Klassen.
Bereiten Sie eine BG_AUTH_CREDENTIALS-Struktur vor. Im Beispiel wird die SecureZeroMemory-Funktion verwendet, um die Speicherspeicherorte zu löschen, die den vertraulichen Informationen zugeordnet sind. Die SecureZeroMemory-Funktion ist in WinBase.h definiert.
Verwenden Sie die GetScheme-Funktion, um das Authentifizierungsschema abzurufen, das zum Herstellen einer Verbindung mit dem Server verwendet werden soll.
bool GetScheme( LPCWSTR s, BG_AUTH_SCHEME *scheme ) { int i; i = 0; while (SchemeNames[i].Name != NULL) { if (0 == _wcsicmp( s, SchemeNames[i].Name )) { *scheme = SchemeNames[i].Scheme; return true; } ++i; } return false; }
Füllen Sie die BG_AUTH_CREDENTIALS-Struktur mit dem von der GetScheme-Funktion zurückgegebenen Authentifizierungsschema sowie dem Benutzernamen und dem Kennwort, die an die Funktion ServerAuthentication übergeben wurden.
Rufen Sie einen Zeiger auf die IBackgroundCopyJob-Schnittstelle (pJob) ab.
Initialisieren Sie die COM-Prozesssicherheit, indem Sie CoInitializeSecurity aufrufen. BITS erfordert mindestens die IMPERSONATE-Ebene des Identitätswechsels. BITS schlägt mit E_ACCESSDENIED fehl, wenn die richtige Identitätswechselebene nicht festgelegt ist.
Rufen Sie einen Zeiger auf die IBackgroundCopyManager-Schnittstelle ab, und rufen Sie den anfänglichen Locator auf BITS ab, indem Sie die CoCreateInstance-Funktion aufrufen.
Erstellen Sie einen BITS-Übertragungsauftrag, indem Sie die IBackgroundCopyManager::CreateJob-Methode aufrufen.
Rufen Sie einen Zeiger auf die CNotifyInterface-Rückrufschnittstelle ab, und rufen Sie die IBackgroundCopyJob::SetNotifyInterface-Methode auf, um Benachrichtigungen über auftragsbezogene Ereignisse zu erhalten. Weitere Informationen zu CNotifyInterface finden Sie unter Beispiel: Allgemeine Klassen.
Rufen Sie die IBackgroundCopyJob::SetNotifyFlags-Methode auf, um die Zu empfangenden Benachrichtigungstypen festzulegen. In diesem Beispiel werden die flags BG_NOTIFY_JOB_TRANSFERRED und BG_NOTIFY_JOB_ERROR festgelegt.
Rufen Sie einen Zeiger auf die IBackgroundCopyJob2-Schnittstelle ab. Verwenden Sie den IBackgroundCopyJob2-Zeiger , um zusätzliche Eigenschaften für den Auftrag festzulegen. Dieses Programm verwendet die IBackgroundCopyJob2::SetCredentials-Methode , um die Anmeldeinformationen für den BITS-Übertragungsauftrag festzulegen.
Fügen Sie dem BITS-Übertragungsauftrag Dateien hinzu, indem Sie IBackgroundCopyJob::AddFile aufrufen. In diesem Beispiel verwendet die IBackgroundCopyJob::AddFile-Methode die Variablen remoteFile und localFile, die an die ServerAuthentication-Funktion übergeben wurden.
Nachdem die Datei hinzugefügt wurde, rufen Sie IBackgroundCopyJob::Resume auf, um den Auftrag fortzusetzen.
Richten Sie eine While-Schleife ein, um auf das Beenden der Nachricht von der Rückrufschnittstelle zu warten, während der Auftrag übertragen wird.
Hinweis
Dieser Schritt ist nur erforderlich, wenn das COM-Apartment ein Singlethread-Apartment ist. Weitere Informationen finden Sie unter Single-Threaded Apartments.
// Wait for QuitMessage from CallBack DWORD dwLimit = GetTickCount() + (15 * 60 * 1000); // set 15 minute limit while (dwLimit > GetTickCount()) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // If it is a quit message, exit. if (msg.message == WM_QUIT) { return; } // Otherwise, dispatch the message. DispatchMessage(&msg); } // End of PeekMessage while loop }
Die vorangehende Schleife verwendet die GetTickCount-Funktion , um die Anzahl von Millisekunden abzurufen, die seit Beginn der Übertragung des Auftrags verstrichen sind.
Nachdem der BITS-Übertragungsauftrag abgeschlossen ist, entfernen Sie den Auftrag aus der Warteschlange, indem Sie IBackgroundCopyJob::Complete aufrufen.
Im folgenden Codebeispiel werden Serverauthentifizierungsanmeldeinformationen für einen BITS-Übertragungsauftrag angegeben.
#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <iostream>
#include <exception>
#include <string>
#include <atlbase.h>
#include <memory>
#include <new>
#include "CommonCode.h"
//
// Retrieve BG_AUTH_SCHEME from scheme name.
//
//
struct
{
LPCWSTR Name;
BG_AUTH_SCHEME Scheme;
}
SchemeNames[] =
{
{ L"basic", BG_AUTH_SCHEME_BASIC },
{ L"digest", BG_AUTH_SCHEME_DIGEST },
{ L"ntlm", BG_AUTH_SCHEME_NTLM },
{ L"negotiate", BG_AUTH_SCHEME_NEGOTIATE },
{ L"passport", BG_AUTH_SCHEME_PASSPORT },
{ NULL, BG_AUTH_SCHEME_BASIC }
};
bool GetScheme( LPCWSTR s, BG_AUTH_SCHEME *scheme )
{
int i;
i = 0;
while (SchemeNames[i].Name != NULL)
{
if (0 == _wcsicmp( s, SchemeNames[i].Name ))
{
*scheme = SchemeNames[i].Scheme;
return true;
}
++i;
}
return false;
}
void ServerAuthentication(const LPWSTR &remoteFile, const LPWSTR &localFile, const LPWSTR &scheme, const LPWSTR &username, const LPWSTR &password)
{
// If CoInitializeEx fails, the exception is unhandled and the program terminates
CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);
// Prepare the credentials structure.
BG_AUTH_CREDENTIALS cred;
ZeroMemory(&cred, sizeof(cred));
if (!GetScheme(scheme,&cred.Scheme))
{
wprintf(L"Invalid authentication scheme specified\n");
return;
}
cred.Target = BG_AUTH_TARGET_SERVER;
cred.Credentials.Basic.UserName = username;
if (0 == _wcsicmp(cred.Credentials.Basic.UserName, L"NULL"))
{
cred.Credentials.Basic.UserName = NULL;
}
cred.Credentials.Basic.Password = password;
if (0 == _wcsicmp(cred.Credentials.Basic.Password, L"NULL"))
{
cred.Credentials.Basic.Password = NULL;
}
CComPtr<IBackgroundCopyJob> pJob;
try
{
//The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
HRESULT hr = CoInitializeSecurity(NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_DYNAMIC_CLOAKING,
0);
if (FAILED(hr))
{
throw MyException(hr, L"CoInitializeSecurity");
}
// Connect to BITS.
CComPtr<IBackgroundCopyManager> pQueueMgr;
hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IBackgroundCopyManager),
(void**)&pQueueMgr);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"CoCreateInstance");
}
// Create a job.
wprintf(L"Creating Job...\n");
GUID guidJob;
hr = pQueueMgr->CreateJob(L"BitsAuthSample",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
&pJob);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"CreateJob");
}
// Set the File Completed call.
CComPtr<CNotifyInterface> pNotify;
pNotify = new CNotifyInterface();
hr = pJob->SetNotifyInterface(pNotify);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"SetNotifyInterface");
}
hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED |
BG_NOTIFY_JOB_ERROR);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"SetNotifyFlags");
}
// Set credentials.
CComPtr<IBackgroundCopyJob2> job2;
hr = pJob.QueryInterface(&job2);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"QueryInterface");
}
hr = job2->SetCredentials(&cred);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"SetCredentials");
}
// Add a file.
wprintf(L"Adding File to Job\n");
hr = pJob->AddFile(remoteFile, localFile);
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"AddFile");
}
//Resume the job.
wprintf(L"Resuming Job...\n");
hr = pJob->Resume();
if (FAILED(hr))
{
// Failed to connect.
throw MyException(hr, L"Resume");
}
}
catch(const std::bad_alloc &)
{
wprintf(L"Memory allocation failed");
if (pJob)
{
pJob->Cancel();
}
return;
}
catch(const MyException &ex)
{
wprintf(L"Error %x occurred during operation", ex.Error);
if (pJob)
{
pJob->Cancel();
}
return;
}
wprintf(L"Transferring file and waiting for callback.\n");
// Wait for QuitMessage from CallBack.
DWORD dwLimit = GetTickCount() + (15 * 60 * 1000); // set 15 minute limit
while (dwLimit > GetTickCount())
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it is a quit message, exit.
if (msg.message == WM_QUIT)
{
return;
}
// Otherwise, dispatch the message.
DispatchMessage(&msg);
} // End of PeekMessage while loop
}
pJob->Cancel();
return;
}
void _cdecl _tmain(int argc, LPWSTR* argv)
{
if (argc != 6)
{
wprintf(L"Usage:");
wprintf(L"%s", argv[0]);
wprintf(L" [remote name] [local name] [server authentication scheme =\"NTLM\"|\"NEGOTIATE\"|\"BASIC\"|\"DIGEST\"] [username] [password]\n");
return;
}
ServerAuthentication(argv[1], argv[2], argv[3], argv[4], argv[5]);
}
Zugehörige Themen