Delen via


Voorbeeld: SSPI-verificatiecodering gebruiken met BITS

U kunt SSPI-verificatiemethoden (Security Support Provider Interface) en BITS-methoden (Background Intelligent Transfer Service) gebruiken om de referenties van een gebruiker op te halen, de referenties te coderen en de gecodeerde referenties in te stellen voor een BITS-overdrachtstaak. Codering is vereist om de structuur van referenties te converteren naar tekenreeksen die kunnen worden doorgegeven aan een BITS-overdrachtstaak.

Zie SSPI-voor meer informatie over SSPI-verificatie en -methoden.

De volgende procedure vraagt om referenties van de gebruiker met behulp van het beveiligingspakket Negotiate. Het programma maakt een verificatie-identiteitsstructuur en vult de structuur met de gecodeerde tekenreeksen die de gebruikersnaam, het domein en het wachtwoord van de gebruiker vertegenwoordigen. Vervolgens maakt het programma een BITS-downloadtaak en stelt u de gecodeerde gebruikersnaam en het wachtwoord in als de referenties voor de taak. Het programma maakt de identiteitsstructuur van de verificatie vrij nadat deze niet meer nodig is.

In dit voorbeeld wordt de header en implementatie gebruikt die zijn gedefinieerd in Voorbeeld: Algemene klassen.

SSPI-verificatiecodering gebruiken met BITS-overdrachtstaken

  1. Initialiseer COM-parameters door de functie CCoInitializer aan te roepen. Zie Voorbeeld: Algemene klassenvoor meer informatie over de functie CCoInitializer.
  2. Aanwijzers ophalen voor de IBackgroundCopyManager, IBackgroundCopyJob, IBackgroundCopyJob2 interfaces. In dit voorbeeld wordt de CComPtr-klasse gebruikt om COM-interfacepointers te beheren.
  3. Maak een CREDUI_INFO structuur die informatie bevat voor het aanpassen van het uiterlijk van het dialoogvenster voor de SspiPromptForCredentials Function. Vraag vervolgens om referenties van de gebruiker. Zie de SspiPromptForCredentials Functionvoor meer informatie.
  4. Codeer de referentiestructuur als tekenreeksen die kunnen worden doorgegeven aan een BITS-overdrachtstaak met behulp van de functie SspiEncodeAuthIdentityAsStrings.
  5. Bereid een BG_AUTH_CREDENTIALS structuur voor.
  6. Initialiseer COM-procesbeveiliging door CoInitializeSecurity-aan te roepen. BITS vereist ten minste het IMITATE-niveau van imitatie. BITS mislukt met E_ACCESSDENIED als het juiste imitatieniveau niet is ingesteld.
  7. Haal de initiƫle locator naar BITS op door de CoCreateInstance-functie aan te roepen.
  8. Maak een BITS-overdrachtstaak door de methode IBackgroundCopyManager::CreateJob aan te roepen.
  9. Haal de id op voor de IBackgroundCopyJob2-interface en roep de methode IBackgroundCopyJob::QueryInterface aan.
  10. Vul de BG_AUTH_CREDENTIALS structuur in met de gecodeerde gebruikersnaam en wachtwoordtekenreeksen en stel het verificatieschema in op Negotiate (BG_AUTH_SCHEME_NEGOTIATE).
  11. Gebruik de IBackgroundCopyJob2 aanwijzer om aanvragen naar BITS te verzenden. Dit programma maakt gebruik van de IBackgroundCopyJob2::SetCredentials methode om de referenties voor de BITS-overdrachtstaak in te stellen.
  12. Voeg bestanden toe, wijzig eigenschappen of hervat de BITS-overdrachtstaak.
  13. Nadat de BITS-overdrachtstaak is voltooid, verwijdert u de taak uit de wachtrij door IBackgroundCopyJob::Completeaan te roepen.
  14. Ten slotte kunt u de identiteitsstructuur van de verificatie vrij maken door de functie SspiFreeAuthIdentity aan te roepen.

In het volgende codevoorbeeld ziet u hoe u SSPI-verificatiecodering gebruikt met BITS-overdrachtstaken.

#define SECURITY_WIN32
#define _SEC_WINNT_AUTH_TYPES

#include <windows.h>
#include <ntsecapi.h>
#include <bits.h>
#include <sspi.h>
#include <wincred.h>
#include <iostream>
#include <atlbase.h>
#include "CommonCode.h"

void PromptForCredentials(PWSTR pwTargetName)
{
    HRESULT hr;
    
    // If CoInitializeEx fails, the exception is unhandled and the program terminates
    CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);
    
    CComPtr<IBackgroundCopyManager> pQueueMgr;
    CComPtr<IBackgroundCopyJob> pJob;
    CComPtr<IBackgroundCopyJob2> pJob2;

    PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentityEx2 = NULL;
    DWORD dwFlags = 0;
    BOOL fSave = FALSE;
    BOOL bReturn = TRUE;

    CREDUI_INFO creduiInfo = { 0 };
    creduiInfo.cbSize = sizeof(creduiInfo);
    // Change the message text and caption to the actual text for your dialog.
    creduiInfo.pszMessageText = pwTargetName;
    creduiInfo.pszCaptionText = L"SSPIPFC title for the dialog box";

    try {
        // Prompt for credentials from user using Negotiate security package.
        DWORD dwRet = SspiPromptForCredentials(
            pwTargetName,
            &creduiInfo,
            0,
            L"Negotiate", 
            NULL,
            &pAuthIdentityEx2,
            &fSave,
            dwFlags
            );

        if (SEC_E_OK != dwRet) 
        {
            // Prompt for credentials failed.
            throw MyException(dwRet, L"SspiPromptForCredentials");
        }

        if (NULL != pAuthIdentityEx2) 
        {
            GUID guidJob;
            BG_AUTH_CREDENTIALS authCreds;

            PCWSTR pwUserName = NULL;
            PCWSTR pwDomainName = NULL;
            PCWSTR pwPassword = NULL;

            // Encode credential structure as strings that can
            // be passed to a BITS job.
            SECURITY_STATUS secStatus = SspiEncodeAuthIdentityAsStrings(
                pAuthIdentityEx2,
                &pwUserName,
                &pwDomainName,
                &pwPassword
                );

            if(SEC_E_OK != secStatus) 
            {
                // Encode authentication identity as strings.
                throw MyException(secStatus, L"SspiEncodeAuthIdentityAsStrings");   
            }

            // Show the encoded user name and domain name.
            wprintf(
                L"User Name: %s\nDomain Name: %s",
                pwUserName,
                pwDomainName
                );

            //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.
            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.
            hr = pQueueMgr->CreateJob(
                L"EncodeSample", 
                BG_JOB_TYPE_DOWNLOAD, 
                &guidJob, 
                &pJob
                );

            if(FAILED(hr))
            {   
                // Failed to create a BITS job.
                throw MyException(hr, L"CreateJob");
            }

            // Get IBackgroundCopyJob2 interface.
            hr = pJob->QueryInterface(__uuidof(IBackgroundCopyJob2), (void**)&pJob2);
            if (FAILED(hr)) 
            {
                // Failed to get a reference to the IBackgroundCopyJob2 interface.
                throw MyException(hr, L"QueryInterface(IBackgroundCopyJob2)");
            }

            // Create a BITS authentication structure from the encoded strings.
            authCreds.Target = BG_AUTH_TARGET_SERVER;
            authCreds.Scheme = BG_AUTH_SCHEME_NEGOTIATE;
            authCreds.Credentials.Basic.UserName = (LPWSTR)pwUserName;
            authCreds.Credentials.Basic.Password = (LPWSTR)pwPassword;

            // Set the credentials for the job.
            hr = pJob2->SetCredentials(&authCreds);
            if (FAILED(hr)) 
            {
                // Failed to set credentials.
                throw MyException(hr, L"SetCredentials");
            }

            // Modify the job's property values.
            // Add files to the job.
            // Activate (resume) the job in the transfer queue.

            // Remove the job from the transfer queue.
            hr = pJob->Complete();
            if (FAILED(hr)) 
            {
                // Failed to complete the job.
                throw MyException(hr, L"Complete");
            }
        }
    }
    catch(std::bad_alloc &)
    {
        wprintf(L"Memory allocation failed");
        if (pJob != NULL)
        {
            pJob->Cancel();
        }
    }
    catch(MyException &ex)
    {
        wprintf(L"Error %x occurred during operation", ex.Error);
        if (pJob != NULL)
        {
            pJob->Cancel();
        }
    }

    // Free the auth identity structure.
    if (NULL != pAuthIdentityEx2)
    {
        SspiFreeAuthIdentity(pAuthIdentityEx2);
        pAuthIdentityEx2 = NULL;
    }

    return;
}

void _cdecl _tmain(int argc, LPWSTR* argv)
{
    PromptForCredentials(L"Target");
}

SSPI-

IBackgroundCopyManager-

IBackgroundCopyJob

IBackgroundCopyJob2

voorbeeld: Algemene klassen