Freigeben über


Beispiel: Hinzufügen eines Hilfstokens zu einem BITS-Übertragungsauftrag

Sie können einen BitS-Transferauftrag (Background Intelligent Transfer Service) mit einem zusätzlichen Sicherheitstoken konfigurieren. Der BITS-Übertragungsauftrag verwendet dieses Hilfstoken für die Authentifizierung und den Zugriff auf Ressourcen.

Weitere Informationen finden Sie unter Hilfstoken für BITS-Übertragungsaufträge.

Im folgenden Verfahren wird ein BITS-Übertragungsauftrag im Kontext des lokalen Benutzers erstellt, Anmeldeinformationen eines zweiten Benutzers abgerufen, ein Hilfstoken mit diesen Anmeldeinformationen erstellt und anschließend das Hilfstoken für den BITS-Übertragungsauftrag festgelegt.

In diesem Beispiel wird der in Beispiel definierte Header und die Implementierung verwendet: Allgemeine Klassen.

So fügen Sie einem BITS-Übertragungsauftrag ein Hilfstoken hinzu

  1. Initialisieren Sie COM-Parameter durch Aufrufen der CCoInitializer-Funktion. Weitere Informationen zur CCoInitializer-Funktion finden Sie unter Beispiel: Allgemeine Klassen.

  2. Rufen Sie einen Zeiger auf die IBackgroundCopyJob- Schnittstelle ab. In diesem Beispiel wird die CComPtr-Klasse zum Verwalten von COM-Schnittstellenzeigern verwendet.

  3. Initialisieren Sie die COM-Prozesssicherheit, indem Sie CoInitializeSecurityaufrufen. BITS erfordert mindestens die Identitätswechselebene. BITS schlägt mit E_ACCESSDENIED fehl, wenn die richtige Identitätswechselebene nicht festgelegt ist.

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

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

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

  7. Rufen Sie die IBackgroundCopyJob::SetNotifyFlags Methode auf, um die Arten von empfangenden Benachrichtigungen festzulegen. In diesem Beispiel werden die Kennzeichnungen BG_NOTIFY_JOB_TRANSFERRED und BG_NOTIFY_JOB_ERROR festgelegt.

  8. Rufen Sie einen Zeiger auf die IBitsTokenOptions- Schnittstelle ab, indem Sie die IBackgroundCopyJob::QueryInterface-Methode mit dem richtigen Schnittstellenbezeichner aufrufen.

  9. Versuchen Sie, sich beim Benutzer des Hilfstokens anzumelden. Erstellen Sie ein Identitätswechselhandle, und rufen Sie die LogonUser Function auf, um das Identitätswechselhandle aufzufüllen. Rufen Sie bei erfolgreicher Ausführung die ImpersonateLoggedOnUser Functionauf. Wenn dies nicht erfolgreich ist, ruft das Beispiel die RevertToSelf Function auf, um den Identitätswechsel des angemeldeten Benutzers zu beenden, wird ein Fehler ausgelöst, und das Handle wird geschlossen.

  10. Rufen Sie die IBitsTokenOptions::SetHelperToken Methode auf, um das Token des angemeldeten Benutzers zu imitieren. Wenn diese Methode fehlschlägt, ruft das Beispiel die RevertToSelf Function auf, um den Identitätswechsel des angemeldeten Benutzers zu beenden, wird ein Fehler ausgelöst, und das Handle wird geschlossen.

    Anmerkung

    In unterstützten Versionen von Windows vor Windows 10, Version 1607, muss der Auftragsbesitzer über Administratoranmeldeinformationen verfügen, um die IBitsTokenOptions::SetHelperToken-Methode aufzurufen.

    Ab Windows 10, Version 1607, können Besitzer von Nicht-Administratoraufträgen Nicht-Administrator-Hilfstoken für BITS-Aufträge festlegen, die sie besitzen. Auftragsbesitzer müssen weiterhin über Administratoranmeldeinformationen verfügen, um Hilfstoken mit Administratorrechten festzulegen.

     

  11. Rufen Sie die IBitsTokenOptions::SetHelperTokenFlags Methode auf, um anzugeben, auf welche Ressourcen mithilfe des Sicherheitskontexts des Hilfstokens zugegriffen werden soll.

  12. Nach Abschluss des Identitätswechsels ruft das Beispiel die RevertToSelf Function auf, um den Identitätswechsel des angemeldeten Benutzers zu beenden, und das Handle wird geschlossen.

  13. Fügen Sie dem BITS-Übertragungsauftrag Dateien hinzu, indem Sie IBackgroundCopyJob::AddFileaufrufen.

  14. Rufen Sie nach dem Hinzufügen der Datei IBackgroundCopyJob::Resume auf, um den Auftrag fortzusetzen.

  15. Richten Sie eine While-Schleife ein, um auf die Quit-Nachricht über die Rückrufschnittstelle zu warten, während der Auftrag übertragen wird. Die While-Schleife verwendet die GetTickCount--Funktion, um die Anzahl von Millisekunden abzurufen, die seit dem Übertragen des Auftrags verstrichen sind.

  16. Nachdem der BITS-Übertragungsauftrag abgeschlossen ist, entfernen Sie den Auftrag aus der Warteschlange, indem Sie IBackgroundCopyJob::Completeaufrufen.

Im folgenden Codebeispiel wird einem BITS-Übertragungsauftrag ein Hilfstoken hinzugefügt.

#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"


void HelperToken(const LPWSTR &remoteFile, const LPWSTR &localFile, const LPWSTR &domain, const LPWSTR &username, const LPWSTR &password)
{
// If CoInitializeEx fails, the exception is unhandled and the program terminates   
CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);

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"HelperTokenSample",
            BG_JOB_TYPE_DOWNLOAD,
            &guidJob,
            &pJob);


        if(FAILED(hr))
        {   
            // Failed to create job.
            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 SetNotifyInterface.
            throw MyException(hr, L"SetNotifyInterface");
        }
        hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED | 
            BG_NOTIFY_JOB_ERROR);

        if (FAILED(hr))
        {
            // Failed to SetNotifyFlags.
            throw MyException(hr, L"SetNotifyFlags");
        }

        //Retrieve the IBitsTokenOptions interface pointer from the BITS transfer job.
        CComPtr<IBitsTokenOptions> pTokenOptions;
        hr = pJob->QueryInterface(__uuidof(IBitsTokenOptions), (void** ) &pTokenOptions);

        if (FAILED(hr))
        {
            // Failed to QueryInterface.
            throw MyException(hr, L"QueryInterface");
        }

        // Log on user of the helper token.
        wprintf(L"Credentials for helper token %s\\%s %s\n", domain, username, password);

        HANDLE hImpersonation = INVALID_HANDLE_VALUE;
        if(LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hImpersonation))
        {
            // Impersonate the logged-on user.
            if(ImpersonateLoggedOnUser(hImpersonation))
            {
                // Configure the impersonated logged-on user's token as the helper token.
                hr = pTokenOptions->SetHelperToken();        
                if (FAILED(hr))
                {
                    //Failed to set helper token.
                    CloseHandle(hImpersonation);
                    RevertToSelf();
                    throw MyException(hr, L"SetHelperToken");
                }

                hr = pTokenOptions->SetHelperTokenFlags(BG_TOKEN_LOCAL_FILE);
                if (FAILED(hr))
                {
                    //Failed to set helper token flags.
                    CloseHandle(hImpersonation);
                    RevertToSelf();
                    throw MyException(hr, L"SetHelperTokenFlags");
                }

                RevertToSelf();
            }               
            CloseHandle(hImpersonation);
        }

        // Add a file.
        // Replace parameters with variables that contain valid paths.
        wprintf(L"Adding File to Job\n");
        hr = pJob->AddFile(remoteFile,localFile);

        if(FAILED(hr))
        {   
            //Failed to add file to job.
            throw MyException(hr, L"AddFile");
        }

        //Resume the job.
        wprintf(L"Resuming Job...\n");
        hr = pJob->Resume();
        if (FAILED(hr))
        {
            // Resume failed.                   
            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 0x%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] [helpertoken domain] [helpertoken userrname] [helpertoken password]\n");
        return;
    }

    HelperToken(argv[1],argv[2],argv[3],argv[4],argv[5]);

}

Hilfstoken für BITS-Übertragungsaufträge

IBitsTokenOptions

Beispiel: Allgemeine Klassen