Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Można określić różne schematy uwierzytelniania dla zadania transferu za pomocą funkcji inteligentnego transferu w tle (BITS).
Poniższa procedura pobiera schemat uwierzytelniania i tworzy strukturę tożsamościową dla uwierzytelniania. Następnie aplikacja tworzy zadanie pobierania usługi BITS i ustawia poświadczenia dla zadania. Po utworzeniu zadania, aplikacja pobiera wskaźnik do interfejsu callback i sprawdza stan zadania transferu BITS. Po zakończeniu zadania zostanie on usunięty z kolejki.
W tym przykładzie użyto nagłówka i implementacji zdefiniowanej w Przykład: Typowe klasy.
Aby określić poświadczenia uwierzytelniania serwera dla zadania transferu usługi BITS
Utwórz strukturę kontenera, która mapuje wartości BG_AUTH_SCHEME do nazw schematów.
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 } };Zainicjuj parametry COM, wywołując funkcję CCoInitializer. Aby uzyskać więcej informacji na temat funkcji CCoInitializer, zobacz Example: Common Classes.
Przygotuj strukturę BG_AUTH_CREDENTIALS. W przykładzie użyto funkcji SecureZeroMemory w celu wyczyszczenia lokalizacji pamięci skojarzonych z poufnymi informacjami. Funkcja SecureZeroMemory jest zdefiniowana w pliku WinBase.h.
Użyj funkcji GetScheme, aby uzyskać schemat uwierzytelniania używany do nawiązywania połączenia z serwerem.
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; }Wypełnij strukturę BG_AUTH_CREDENTIALS schematem uwierzytelniania zwróconym przez funkcję GetScheme oraz nazwę użytkownika i hasło, które zostały przekazane do funkcji ServerAuthentication.
Pobierz wskaźnik do interfejsu IBackgroundCopyJob (pJob).
Inicjowanie zabezpieczeń procesu COM przez wywołanie CoInitializeSecurity. Usługa BITS wymaga co najmniej poziomu "IMPERSONATE" dla uwierzytelnienia. Usługa BITS kończy się niepowodzeniem z E_ACCESSDENIED, jeśli nie ustawiono poprawnego poziomu impersonacji.
Pobierz wskaźnik do interfejsu IBackgroundCopyManager i uzyskaj początkowy lokalizator do usługi BITS, wywołując funkcję CoCreateInstance.
Utwórz zadanie transferu usługi BITS, wywołując metodę IBackgroundCopyManager::CreateJob.
Pobierz wskaźnik do interfejsu wywołania zwrotnego CNotifyInterface i wywołaj metodę IBackgroundCopyJob::SetNotifyInterface, aby otrzymywać powiadomienia o zdarzeniach związanych z zadaniem. Aby uzyskać więcej informacji na temat CNotifyInterface, zobacz Example: Common Classes.
Wywołaj metodę IBackgroundCopyJob::SetNotifyFlags, aby ustawić typy powiadomień do odbierania. W tym przykładzie ustawiono flagi BG_NOTIFY_JOB_TRANSFERRED i BG_NOTIFY_JOB_ERROR.
Uzyskaj wskaźnik do interfejsu IBackgroundCopyJob2. Użyj wskaźnika IBackgroundCopyJob2, aby ustawić dodatkowe właściwości zadania. Ten program używa metody IBackgroundCopyJob2::SetCredentials, aby ustawić poświadczenia dla zadania transferu usługi BITS.
Dodaj pliki do zadania transferu usługi BITS, wywołując IBackgroundCopyJob::AddFile. W tym przykładzie metoda IBackgroundCopyJob::AddFile używa zmiennych remoteFile i localFile, które zostały przekazane do funkcji ServerAuthentication.
Po dodaniu pliku wywołaj IBackgroundCopyJob::Resume, aby wznowić zadanie.
Skonfiguruj pętlę while, aby poczekać na komunikat o zakończeniu z interfejsu wywołania zwrotnego, kiedy zadanie jest przesyłane.
Notatka
Ten krok jest niezbędny tylko wtedy, gdy mieszkanie COM jest jednowątkowym apartamentem. Aby uzyskać więcej informacji, zobacz 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 }Poprzednia pętla używa funkcji GetTickCount, aby pobrać liczbę milisekund, które upłynęły od momentu rozpoczęcia przesyłania zadania.
Po zakończeniu zadania transferu BITS, usuń zadanie z kolejki, wywołując IBackgroundCopyJob::Complete.
Poniższy przykład kodu określa poświadczenia uwierzytelniania serwera dla zadania transferu usługi BITS.
#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]);
}
Tematy pokrewne