Szybki start: inicjowanie aplikacji klienckiej dla zestawów SDK ochrony (C++)

W tym przewodniku Szybki start pokazano, jak zaimplementować wzorzec inicjowania klienta używany przez zestaw MIP C++ SDK w czasie wykonywania.

Uwaga / Notatka

Każda aplikacja kliencka korzystająca z zestawów SDK usługi MIP Protection wymaga wykonania kroków opisanych w tym przewodniku Szybki start. Wykonaj kolejno te przewodniki Szybki start po zainicjowaniu aplikacji oraz zaimplementowaniu klas delegatów uwierzytelniania i zgody.

Wymagania wstępne

Jeśli jeszcze tego nie zrobiono, upewnij się, że:

Tworzenie rozwiązania i projektu programu Visual Studio

Najpierw utwórz i skonfiguruj początkowe rozwiązanie oraz projekt programu Visual Studio, na których bazują inne przewodniki z serii Szybki start.

  1. Otwórz program Visual Studio 2022 lub nowszy, wybierz menu Plik , Nowy, Projekt. W oknie dialogowym Nowy projekt :

    • W okienku po lewej stronie w obszarze Zainstalowaneinne języki wybierz pozycję Visual C++.

    • W środkowym okienku wybierz pozycję Aplikacja konsolowa systemu Windows.

    • W dolnym okienku zaktualizuj odpowiednio nazwę projektu,lokalizację i nazwę rozwiązania zawierającego.

    • Po zakończeniu wybierz przycisk OK w prawym dolnym rogu.

      Tworzenie rozwiązania w programie Visual Studio.

  2. Dodaj pakiet NuGet dla zestawu MIP Protection SDK do projektu:

    • W Eksplorator rozwiązań kliknij prawym przyciskiem myszy węzeł projektu bezpośrednio w górnym węźle rozwiązania, a następnie wybierz polecenie Zarządzaj pakietami NuGet...:

    • Po otwarciu karty Menedżer pakietów NuGet w obszarze kart Grupy edytora:

      • Wybierz przycisk Przeglądaj.
      • W polu wyszukiwania wpisz Microsoft.InformationProtection.
      • Microsoft.InformationProtection.Protection Wybierz pakiet.
      • Wybierz pozycję Zainstaluj, a następnie wybierz przycisk OK po wyświetleniu okna dialogowego potwierdzenia zmiany podglądu .

      Visual Studio dodać pakiet NuGet.

Implementowanie klas obserwatorów do monitorowania profilu ochrony i obiektów silnika

Teraz utwórz podstawową implementację klasy obserwatora profilu ochrony, rozszerzając klasę zestawu SDK mip::ProtectionProfile::Observer . SDK tworzy instancję obserwatora i używa jej później do monitorowania ładowania obiektu profilu ochrony oraz do dodawania obiektu silnika do profilu.

  1. Dodaj nową klasę do projektu, która generuje pliki nagłówka (.h) i implementacji (.cpp):

    • W Eksplorator rozwiązań ponownie kliknij prawym przyciskiem myszy węzeł projektu, wybierz polecenie Dodaj, a następnie wybierz pozycję Klasa.

    • W oknie dialogowym Dodawanie klasy :

      • W polu Nazwa klasy wprowadź wartość profile_observer. Zwróć uwagę, że Visual Studio automatycznie wypełnia pola pliku .h i .cpp na podstawie wprowadzonej nazwy.
      • Po zakończeniu wybierz przycisk OK.

      Visual Studio dodaj klasę.

  2. Po wygenerowaniu plików h i .cpp dla klasy Visual Studio otwiera oba pliki na kartach Grupy edytora. Teraz zaktualizuj każdy plik, aby zaimplementować nową klasę obserwatora:

    • Zaktualizuj profile_observer.h , wybierając i usuwając wygenerowaną profile_observer klasę. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj i wklej następujące źródło do pliku po istniejących dyrektywach preprocesora:

      #include <memory>
      #include "mip/protection/protection_profile.h"
      using std::exception_ptr;
      using std::shared_ptr;
      
      
      class ProtectionProfileObserver final : public mip::ProtectionProfile::Observer {
      public:
           ProtectionProfileObserver() { }
           void OnLoadSuccess(const std::shared_ptr<mip::ProtectionProfile>& profile, const std::shared_ptr<void>& context) override;
           void OnLoadFailure(const std::exception_ptr& Failure, const std::shared_ptr<void>& context) override;
           void OnAddEngineSuccess(const std::shared_ptr<mip::ProtectionEngine>& engine, const std::shared_ptr<void>& context) override;
           void OnAddEngineFailure(const std::exception_ptr& Failure, const std::shared_ptr<void>& context) override;
      };
      
    • Zaktualizuj profile_observer.cpp , wybierając i usuwając implementację wygenerowanej profile_observer klasy. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj i wklej następujące źródło do pliku po istniejących dyrektywach preprocesora:

      #include <future>
      
      using std::promise;
      using std::shared_ptr;
      using std::static_pointer_cast;
      using mip::ProtectionEngine;
      using mip::ProtectionProfile;
      
      void ProtectionProfileObserver::OnLoadSuccess(const shared_ptr<ProtectionProfile>& profile, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionProfile>>>(context);
           promise->set_value(profile);
      }
      
      void ProtectionProfileObserver::OnLoadFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionProfile>>>(context);
           promise->set_exception(error);
      }
      
      void ProtectionProfileObserver::OnAddEngineSuccess(const shared_ptr<ProtectionEngine>& engine, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionEngine>>>(context);
           promise->set_value(engine);
      }
      
      void ProtectionProfileObserver::OnAddEngineFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionEngine>>>(context);
           promise->set_exception(error);
      }
      
  3. Powtórz krok 1, aby dodać nową klasę dla obserwatora aparatu ochrony, engine_observer, do projektu. Ta klasa generuje dla Ciebie zarówno pliki nagłówkowe (.h), jak i pliki implementacji (.cpp).

  4. Po wygenerowaniu plików h i .cpp dla klasy Visual Studio otwiera oba pliki na kartach Grupy edytora. Teraz zaktualizuj każdy plik, aby zaimplementować nową klasę obserwatora:

    • Zaktualizuj engine_observer.h , wybierając i usuwając wygenerowaną engine_observer klasę. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj i wklej następujące źródło do pliku po istniejących dyrektywach preprocesora:

      #include <memory>
      #include "mip/protection/protection_engine.h"
      using std::vector;
      using std::exception_ptr;
      using std::shared_ptr;
      
      class ProtectionEngineObserver final : public mip::ProtectionEngine::Observer {
        public:
        ProtectionEngineObserver() {}
        void OnGetTemplatesSuccess(const vector<std::shared_ptr<mip::TemplateDescriptor>>& templateDescriptors, const shared_ptr<void>& context) override;
        void OnGetTemplatesFailure(const exception_ptr& Failure, const shared_ptr<void>& context) override;
      
      };
      
    • Zaktualizuj engine_observer.cpp , wybierając i usuwając implementację wygenerowanej engine_observer klasy. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj i wklej następujące źródło do pliku po istniejących dyrektywach preprocesora:

      #include "mip/protection/protection_profile.h"
      #include "engine_observer.h"
      
      using std::promise;
      void ProtectionEngineObserver::OnGetTemplatesSuccess(const vector<shared_ptr<mip::TemplateDescriptor>>& templateDescriptors,const shared_ptr<void>& context) {
          auto loadPromise = static_cast<promise<vector<shared_ptr<mip::TemplateDescriptor>>>*>(context.get());
          loadPromise->set_value(templateDescriptors);
        };
      
        void ProtectionEngineObserver::OnGetTemplatesFailure(const exception_ptr& Failure, const shared_ptr<void>& context) {
          auto loadPromise = static_cast<promise<vector<shared_ptr<mip::TemplateDescriptor>>>*>(context.get());
          loadPromise->set_exception(Failure);
        };
      
  5. Opcjonalnie użyj klawiszy Ctrl+Shift+B (kompiluj rozwiązanie), aby uruchomić kompilację testową i link rozwiązania, aby sprawdzić, czy kompilacja została pomyślnie skompilowana przed kontynuowaniem.

Zestaw SDK MIP implementuje uwierzytelnianie poprzez mechanizm rozszerzania klas, który umożliwia współdzielenie z aplikacją kliencką zadań związanych z uwierzytelnianiem. Klient musi uzyskać odpowiedni token dostępu OAuth2 i udostępnić go zestawowi MIP SDK w czasie wykonywania.

Utwórz implementację delegata uwierzytelniania, dziedzicząc po klasie SDK mip::AuthDelegate i nadpisując/implementując czysto wirtualną funkcję mip::AuthDelegate::AcquireOAuth2Token(). Postępuj zgodnie z instrukcjami opisanymi w temacie File SDK application initialization quickstart (Szybki start inicjowania aplikacji zestawu SDK plików). Obiekty profilu ochrony i mechanizmu ochrony tworzą delegata uwierzytelniania, a następnie go używają.

Teraz utwórz implementację delegata zgody, rozszerzając klasę zestawu SDK mip::ConsentDelegate i przesłaniając/implementując czystą funkcję wirtualną mip::AuthDelegate::GetUserConsent() . Postępuj zgodnie z instrukcjami opisanymi w temacie File SDK application initialization quickstart (Szybki start inicjowania aplikacji zestawu SDK plików). Obiekty profilu ochrony i silnika ochrony tworzą instancje i później używają delegata zgody.

Konstruowanie profilu i aparatu ochrony

Jak wspomniano, klienci zestawu SDK korzystający z interfejsów API MIP wymagają obiektów profilu i silnika. Ukończ część tego przewodnika szybkiego startu dotyczącą kodu, dodając kod w celu utworzenia instancji obiektów profilu i silnika:

  1. W Eksploratorze rozwiązań otwórz plik .cpp w projekcie zawierający implementację main() metody . Domyślnie ma taką samą nazwę jak projekt zawierający go, który został określony podczas tworzenia projektu.

  2. Usuń wygenerowaną implementację elementu main(). Nie usuwaj dyrektyw preprocesora generowanych przez program Visual Studio podczas tworzenia projektu (#pragma, #include). Dołącz następujący kod po wszelkich dyrektywach preprocesora:

#include "mip/mip_context.h"  
#include "auth_delegate.h"
#include "consent_delegate.h"
#include "profile_observer.h"
#include"engine_observer.h"

using std::promise;
using std::future;
using std::make_shared;
using std::shared_ptr;
using std::string;
using std::cout;
using mip::ApplicationInfo;
using mip::ProtectionProfile;
using mip::ProtectionEngine;

int main(){

  // Construct/initialize objects required by the application's profile object
  // ApplicationInfo object (App ID, name, version)
  ApplicationInfo appInfo{"<application-id>",                    
                          "<application-name>",
                          "<application-version>"};

  std::shared_ptr<mip::MipConfiguration> mipConfiguration = std::make_shared<mip::MipConfiguration>(appInfo,
				                                                                                               "mip_data",
                                                                                      			         mip::LogLevel::Trace,
                                                                                                     false,
                                                                                                     mip::CacheStorageType::OnDisk);

  std::shared_ptr<mip::MipContext> mMipContext = mip::MipContext::Create(mipConfiguration);

  auto profileObserver = make_shared<ProtectionProfileObserver>(); // Observer object
  auto authDelegateImpl = make_shared<AuthDelegateImpl>("<application-id>"); // Authentication delegate object (App ID)
  auto consentDelegateImpl = make_shared<ConsentDelegateImpl>(); // Consent delegate object

  // Construct/initialize profile object
  ProtectionProfile::Settings profileSettings(
    mMipContext,
    mip::CacheStorageType::OnDisk,      
    consentDelegateImpl,
    profileObserver);

  // Set up promise/future connection for async profile operations; load profile asynchronously
  auto profilePromise = make_shared<promise<shared_ptr<ProtectionProfile>>>();
  auto profileFuture = profilePromise->get_future();
  try
  {
    mip::ProtectionProfile::LoadAsync(profileSettings, profilePromise);
  }
  catch (const std::exception& e)
  {
    cout << "An exception occurred... are the Settings and ApplicationInfo objects populated correctly?\n\n"
          << e.what() << "'\n";
    system("pause");
    return 1;
  }

  auto profile = profileFuture.get();

  // Construct/initialize engine object
  ProtectionEngine::Settings engineSettings(       
     mip::Identity("<engine-account>"),         // Engine identity (account used for authentication)
     authDelegateImpl,                          // Reference to mip::AuthDelegate implementation
     "",                                        // ClientData field
     "en-US");                                  // Locale (default = en-US)

  // Set the engineId so it can be cached and reused. 
  engineSettings.SetEngineId("<engine-account>");

  // Set up promise/future connection for async engine operations; add engine to profile asynchronously
  auto enginePromise = make_shared<promise<shared_ptr<ProtectionEngine>>>();
  auto engineFuture = enginePromise->get_future();
  profile->AddEngineAsync(engineSettings, enginePromise);
  std::shared_ptr<ProtectionEngine> engine;

  try
  {
    engine = engineFuture.get();
  }
  catch (const std::exception& e)
  {
    cout << "An exception occurred... is the access token incorrect/expired?\n\n"
         << e.what() << "'\n";
    system("pause");
    return 1;
  }

  // Application shutdown. Null out profile and engine, call ReleaseAllResources();
  // Application may crash at shutdown if resources aren't properly released.
  engine = nullptr;
  profile = nullptr;
  mMipContext->ShutDown();
  mMipContext = nullptr;

  return 0;
}
  1. Zastąp wszystkie wartości zastępcze w kodzie źródłowym, który wkleiłeś, za pomocą stałych znakowych:

    Zastępczy element Wartość Przykład
    <identyfikator aplikacji> Identyfikator aplikacji (GUID) Microsoft Entra przypisany do aplikacji zarejestrowanej w kroku 2 artykułu Konfiguracja i konfiguracja zestawu MIP SDK. Zastąp 2 wystąpienia. "00001111-aaaa-2222-bbbb-3333cccc4444"
    <nazwa aplikacji> Przyjazna nazwa aplikacji zdefiniowana przez użytkownika. Musi zawierać prawidłowe znaki ASCII (z wyjątkiem "; ") i najlepiej pasuje do nazwy aplikacji użytej w Microsoft Entra rejestracji. "AppInitialization"
    <wersja aplikacji> Informacje o wersji zdefiniowanej przez użytkownika dla aplikacji. Musi zawierać prawidłowe znaki ASCII (z wyłączeniem znaku ";"). "1.1.0.0"
    <konto silnika> Konto używane do obsługi tożsamości aparatu. Podczas uwierzytelniania przy użyciu konta użytkownika podczas pozyskiwania tokenu musi być zgodna z tą wartością. "user1@tenant.onmicrosoft.com"
    <stan silnika> Stan zdefiniowany przez użytkownika skojarzony z silnikiem. "My App State"
  2. Teraz wykonaj ostateczną kompilację aplikacji i rozwiąż wszelkie błędy. Kod powinien kompilować się pomyślnie, ale nie działa poprawnie, dopóki nie ukończysz następnego przewodnika Szybki start. Jeśli uruchomisz aplikację, zobaczysz dane wyjściowe podobne do poniższych. Aplikacja pomyślnie tworzy profil zabezpieczeń i mechanizm ochrony, ale nie wywołuje modułu uwierzytelniania i nie uzyskasz tokenu dostępu, dopóki nie ukończysz kolejnego samouczka z serii Szybki start.

     C:\MIP Sample Apps\ProtectionQS\Debug\ProtectionQS.exe (process 8252) exited with code 0.
     To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
     Press any key to close this window . . .
    

Następne kroki

Teraz, gdy ukończono kod inicjalizacyjny, możesz przejść do kolejnego przewodnika z serii Szybki start, w którym rozpoczniesz pracę z pakietem MIP Protection SDK.