Freigeben über


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

  1. 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 }
    };
    
  2. Initialisieren Sie COM-Parameter, indem Sie die CCoInitializer-Funktion aufrufen. Weitere Informationen zur CCoInitializer-Funktion finden Sie unter Beispiel: Allgemeine Klassen.

  3. 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.

  4. 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;
    }
    
  5. 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.

  6. Rufen Sie einen Zeiger auf die IBackgroundCopyJob-Schnittstelle (pJob) ab.

  7. 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.

  8. 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.

  9. Erstellen Sie einen BITS-Übertragungsauftrag, indem Sie die IBackgroundCopyManager::CreateJob-Methode aufrufen.

  10. 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.

  11. 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.

  12. 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.

  13. 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.

  14. Nachdem die Datei hinzugefügt wurde, rufen Sie IBackgroundCopyJob::Resume auf, um den Auftrag fortzusetzen.

  15. 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.

  16. 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]); 

}

IBackgroundCopyManager

IBackgroundCopyJob

IBackgroundCopyJob2

Beispiel: Allgemeine Klassen