Udostępnij przez


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

W przewodniku "Szybki start" przedstawiono, jak zaimplementować wzorzec inicjowania klienta używany przez SDK MIP C++ w trakcie działania.

Uwaga / Notatka

Kroki opisane w tym szybkim starcie są wymagane dla aplikacji klienckiej korzystającej z SDK ochrony MIP. Te szybkie starty powinny być wykonywane szeregowo, po zainicjowaniu aplikacji i implementacji klas delegatów uwierzytelniania oraz zgody.

Wymagania wstępne

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

Tworzenie rozwiązania i projektu programu Visual Studio

Najpierw utworzymy i skonfigurujemy początkowe rozwiązanie i projekt programu Visual Studio, na którym bazują inne szybkie starty.

  1. Otwórz program Visual Studio 2019 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 kliknij przycisk OK w prawym dolnym rogu.

      Tworzenie rozwiązania programu Visual Studio

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

    • W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł projektu (bezpośrednio w węźle u góry/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.
      • Wpisz "Microsoft.InformationProtection" w polu wyszukiwania.
      • Wybierz pakiet "Microsoft.InformationProtection.Protection".
      • Kliknij "Zainstaluj", a następnie kliknij "OK", gdy zostanie wyświetlone okno dialogowe potwierdzenia 'Podgląd zmian'.

      Dodawanie pakietu NuGet w programie Visual Studio

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 . Obserwator jest tworzony i używany później do monitorowania ładowania obiektu profilu Zabezpieczenia oraz dodawania obiektu silnika do profilu.

  1. Dodaj nową klasę do projektu, która generuje pliki header/.h i implementation/.cpp dla Ciebie:

    • W Eksploratorze 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ź "profile_observer". Zwróć uwagę, że zarówno plik h , jak i pola pliku .cpp są wypełniane automatycznie na podstawie wprowadzonej nazwy.
      • Po zakończeniu kliknij przycisk OK .

      Dodaj klasę w Visual Studio

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

    • Zaktualizuj element "profile_observer.h", wybierając/usuwając wygenerowaną profile_observer klasę. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj/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 lub usuwając implementację wygenerowanej klasy profile_observer. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj/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. Wykonaj kroki opisane w kroku 1. Dodaj nową klasę dla obserwatora silnika ochrony — "engine_observer" do swojego projektu, która generuje zarówno pliki nagłówkowe/.h, jak i implementacyjne/.cpp.

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

    • Zaktualizuj "engine_observer.h", wybierając/usuwając wygenerowaną engine_observer klasę. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj/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 element "engine_observer.cpp", wybierając/usuwając implementację wygenerowanej engine_observer klasy. Nie usuwaj dyrektyw preprocesora wygenerowanych w poprzednim kroku (#pragma, #include). Następnie skopiuj/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<shared_ptr<mip::ProtectionProfile>>*>(context.get());
          loadPromise->set_exception(Failure);
        };
      
  5. Opcjonalnie użyj Ctrl+Shift+B (Kompiluj rozwiązanie), aby uruchomić kompilowanie/łącze testowe rozwiązania, aby upewnić się, że kompiluje się pomyślnie przed kontynuowaniem.

Zestaw MIP SDK implementuje uwierzytelnianie przy użyciu rozszerzalności klas, co zapewnia mechanizm udostępniania pracy uwierzytelniania z aplikacją kliencką. Klient musi uzyskać odpowiedni token dostępu OAuth2 i przekazać go do MIP SDK podczas działania.

Utwórz implementację delegata uwierzytelniania, rozszerzając klasę SDK mip::AuthDelegate i przesłaniając/implementując funkcję czysto wirtualną mip::AuthDelegate::AcquireOAuth2Token(). Wykonaj kroki opisane w sekcji File SDK Application Initialization Quickstart. Delegat uwierzytelniania jest tworzony i używany później przez obiekty profilu ochrony i silnika ochrony.

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() . Wykonaj kroki opisane w sekcji File SDK Application Initialization Quickstart. Delegat zgody jest tworzony i używany później przez obiekty profilu ochrony i silnika ochrony.

Konstruowanie profilu i aparatu ochrony

Jak wspomniano, obiekty profilu i silnika są wymagane dla klientów zestawu SDK przy użyciu interfejsów API MIP. Ukończ część kodowania tego Quickstartu, dodając kod, aby utworzyć wystąpienia 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_init.h"
#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>(mAppInfo,
				                                                                                               "mip_data",
                                                                                      			         mip::LogLevel::Trace,
                                                                                                     false);

  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;
  mipContext.Shutdown();
  mipContext = nullptr;

  return 0;
}
  1. Zastąp wszystkie wartości symboli zastępczych w kodzie źródłowym, który właśnie wkleiłeś, używając stałych ciągów:

    Zastępczy element Wartość Przykład
    <identyfikator aplikacji> Identyfikator aplikacji Microsoft Entra (GUID) przypisany do aplikacji zarejestrowanej w kroku 2 artykułu "Konfiguracja i konfiguracja zestawu MIP SDK" (setup-configure-mip.md). Zastąp 2 wystąpienia. "0edbblll-8773-44de-b87c-b8c6276d41eb"
    <nazwa aplikacji> Przyjazna nazwa aplikacji zdefiniowana przez użytkownika. Musi zawierać prawidłowe znaki ASCII (z wyłączeniem znaku ";") i najlepiej odpowiada nazwie aplikacji użytej w rejestracji firmy Microsoft Entra. "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 do skojarzenia z aparatem. "My App State"
  2. Teraz wykonaj ostateczną kompilację aplikacji i rozwiąż wszelkie błędy. Kod powinien zostać skompilowany pomyślnie, ale nie zostanie jeszcze uruchomiony poprawnie, dopóki nie ukończysz następnego Quickstart. Jeśli uruchomisz aplikację, zobaczysz dane wyjściowe podobne do poniższych. Aplikacja pomyślnie skonstruuje profil ochrony i aparat ochrony, ale nie zostałby wyzwolony moduł uwierzytelniania i nie będzie jeszcze mieć tokenu dostępu do momentu ukończenia następnego przewodnika 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 . . .
    

Dalsze kroki

Teraz, gdy kod inicjowania został ukończony, możesz przystąpić do następnego przewodnika Szybki start, w którym zaczniesz korzystać z zestawu MIP Protection SDK.