Guia de início rápido: inicialização do aplicativo cliente (C++)

Este quickstart mostra-lhe como implementar o padrão de inicialização do cliente que o SDK MIP C++ usa em tempo de execução.

Observação

Qualquer aplicação cliente que utilize os SDKs MIP de Ficheiro, Política ou Proteção requer que siga os passos descritos neste guia de iniciação rápida. Embora este início rápido demonstre o uso dos SDKs de ficheiros, este mesmo padrão aplica-se a clientes que utilizam os SDKs de Política e Protecção. Conclua os restantes guias de iniciação rápida de forma sequencial, porque cada um se baseia no anterior, sendo este o primeiro deles.

Pré-requisitos

Se ainda não o fez, certifique-se de:

Criar uma solução e um projeto do Visual Studio

Primeiro, crie e configure a solução inicial do Visual Studio e o projeto, sobre os quais os outros quickstarts constroem.

  1. Abra o Visual Studio 2022 ou versão posterior, selecione o menu Ficheiro , Novo, Projeto. Na caixa de diálogo Novo projeto :

    • No painel esquerdo, em Instalado, Outros Idiomas, selecione Visual C++.

    • No painel central, selecione Aplicativo de Console do Windows

    • No painel inferior, atualize o nome do projeto, o local e o nome da solução que o contém de acordo.

    • Quando terminar, clique no botão OK no canto inferior direito.

      Criação de soluções no Visual Studio.

  2. Adicione o pacote NuGet para o SDK de arquivo MIP ao seu projeto:

    • No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto (diretamente abaixo do nó superior/solução) e selecione Gerenciar pacotes NuGet...:

    • Quando a guia Gestor de Pacotes NuGet é aberta na área de guias da secção Grupo de Editores:

      • Selecione Procurar.
      • Digite "Microsoft.InformationProtection" na caixa de pesquisa.
      • Selecione o pacote "Microsoft.InformationProtection.File".
      • Clique em "Instalar" e, em seguida, clique em "OK" quando a caixa de diálogo de confirmação de alterações de visualização for exibida.

      O Visual Studio adiciona o pacote NuGet.

Implementar uma classe observadora para monitorar o perfil File e os objetos do engine

Agora crie uma implementação básica para uma classe de observador de perfil de ficheiro estendendo a classe do mip::FileProfile::Observer SDK. Instancias e usas o observador mais tarde para monitorizar o carregamento do objeto de perfil de ficheiro e adicionar o objeto motor ao perfil.

  1. Adicione uma nova classe ao seu projeto, que gera os arquivos header/.h e implementation/.cpp para você:

    • No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto novamente, selecione Adicionar e, em seguida, selecione Classe.

    • Na caixa de diálogo Adicionar classe :

      • No campo Nome da classe , digite "profile_observer". Observe que os campos de arquivo .h e arquivo .cpp são preenchidos automaticamente, com base no nome inserido.
      • Quando terminar, clique no botão OK .

      Visual Studio adiciona classe.

  2. Depois de gerar os ficheiros .h e .cpp para a classe, o Visual Studio abre ambos os ficheiros nos separadores do grupo do editor. Agora atualize cada arquivo para implementar sua nova classe de observador:

    • Atualize "profile_observer.h", selecionando/excluindo a classe gerada profile_observer . Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include). Em seguida, copie/cole a seguinte fonte no arquivo, após quaisquer diretivas de pré-processador existentes:

      #include <memory>
      #include "mip/file/file_profile.h"
      
      class ProfileObserver final : public mip::FileProfile::Observer {
      public:
           ProfileObserver() { }
           void OnLoadSuccess(const std::shared_ptr<mip::FileProfile>& profile, const std::shared_ptr<void>& context) override;
           void OnLoadFailure(const std::exception_ptr& error, const std::shared_ptr<void>& context) override;
           void OnAddEngineSuccess(const std::shared_ptr<mip::FileEngine>& engine, const std::shared_ptr<void>& context) override;
           void OnAddEngineFailure(const std::exception_ptr& error, const std::shared_ptr<void>& context) override;
      };
      
    • Atualize "profile_observer.cpp", selecionando/excluindo a implementação da classe gerada profile_observer . Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include). Em seguida, copie/cole a seguinte fonte no arquivo, após quaisquer diretivas de pré-processador existentes:

      #include <future>
      
      using std::promise;
      using std::shared_ptr;
      using std::static_pointer_cast;
      using mip::FileEngine;
      using mip::FileProfile;
      
      void ProfileObserver::OnLoadSuccess(const shared_ptr<FileProfile>& profile, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<FileProfile>>>(context);
           promise->set_value(profile);
      }
      
      void ProfileObserver::OnLoadFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<FileProfile>>>(context);
           promise->set_exception(error);
      }
      
      void ProfileObserver::OnAddEngineSuccess(const shared_ptr<FileEngine>& engine, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<FileEngine>>>(context);
           promise->set_value(engine);
      }
      
      void ProfileObserver::OnAddEngineFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<FileEngine>>>(context);
           promise->set_exception(error);
      }
      
  3. Opcionalmente, use F6 (Build Solution) para executar uma compilação/link de teste da sua solução, para garantir que ela seja compilada com êxito antes de continuar.

Implementar um delegado de autenticação

O SDK MIP implementa a autenticação através da extensibilidade de classes, que fornece um mecanismo para partilhar o trabalho de autenticação com a aplicação cliente. O cliente deve adquirir um token de acesso OAuth2 adequado e fornecê-lo ao MIP SDK em tempo de execução.

Agora crie uma implementação para um delegado de autenticação estendendo a classe do mip::AuthDelegate SDK e sobrescrevendo ou implementando a mip::AuthDelegate::AcquireOAuth2Token() função puramente virtual. O perfil de ficheiro e os objetos do motor de ficheiros instanciam-se e usam o delegado de autenticação mais tarde.

  1. Usando o mesmo recurso "Adicionar classe" do Visual Studio que usamos na etapa #1 da seção anterior, adicione outra classe ao seu projeto. Desta vez, digite "auth_delegate" no campo Nome da classe .

  2. Agora atualize cada arquivo para implementar sua nova classe de delegado de autenticação:

    • Atualize "auth_delegate.h", substituindo todo o código de classe gerado auth_delegate pela seguinte fonte. Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include):

      #include <string>
      #include "mip/common_types.h"
      
      class AuthDelegateImpl final : public mip::AuthDelegate {
      public:
           AuthDelegateImpl() = delete;        // Prevents default constructor
      
           AuthDelegateImpl(
             const std::string& appId)         // AppID for registered Microsoft Entra app
             : mAppId(appId) {};
      
           bool AcquireOAuth2Token(                     // Called by MIP SDK to get a token
             const mip::Identity& identity,             // Identity of the account to be authenticated, if known
             const OAuth2Challenge& challenge,          // Authority (Microsoft Entra tenant issuing token), and resource (API being accessed; "aud" claim).
             const std::shared_ptr<void>& context,      // Opaque context passed by the host application through the MIP API
             OAuth2Token& token) override;              // Token handed back to MIP SDK
      
      private:
           std::string mAppId;
           std::string mToken;
           std::string mAuthority;
           std::string mResource;
      };
      
    • Atualize "auth_delegate.cpp", substituindo toda a implementação de classe gerada auth_delegate pelo código-fonte seguinte. Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include).

      Important

      O seguinte código de aquisição de token não é adequado para uso em produção. Em produção, substitua-o por código que adquira dinamicamente um token ao usar:

      • O appId e o URI de resposta/redirecionamento especificados no registro do aplicativo Microsoft Entra (o URI de resposta/redirecionamento deve corresponder ao registro do aplicativo)
      • A autoridade e a URL do recurso passadas pelo SDK no argumento (a URL do recurso challenge deve corresponder às API/permissões do registo da aplicação)
      • Credenciais válidas de aplicativo/usuário, onde a conta corresponde ao identity argumento passado pelo SDK. Os clientes "nativos" OAuth2 devem solicitar credenciais de usuário e usar o fluxo de "código de autorização". Os "clientes confidenciais" OAuth2 podem usar suas próprias credenciais seguras com o fluxo de "credenciais de cliente" (como um serviço) ou solicitar credenciais de usuário usando o fluxo de "código de autorização" (como um aplicativo Web).

      A aquisição de tokens OAuth2 é um protocolo complexo e normalmente é realizada através da utilização de uma biblioteca. TokenAcquireOAuth2Token() é chamado apenas pelo MIP SDK, conforme necessário.

      #include <iostream>
      using std::cout;
      using std::cin;
      using std::string;
      
      bool AuthDelegateImpl::AcquireOAuth2Token(const mip::Identity& identity, const OAuth2Challenge& challenge, const std::shared_ptr<void>& context, OAuth2Token& token) 
      {
           (void)context;
           // Acquire a token manually, reuse previous token if same authority/resource. In production, replace with token acquisition code.
           string authority = challenge.GetAuthority();
           string resource = challenge.GetResource();
           if (mToken == "" || (authority != mAuthority || resource != mResource))
           {
               cout << "\nRun the PowerShell script to generate an access token using the following values, then copy/paste it below:\n";
               cout << "Set $authority to: " + authority + "\n";
               cout << "Set $resourceUrl to: " + resource + "\n";
               cout << "Sign in with user account: " + identity.GetEmail() + "\n";
               cout << "Enter access token: ";
               cin >> mToken;
               mAuthority = authority;
               mResource = resource;
               system("pause");
           }
      
           // Pass access token back to MIP SDK
           token.SetAccessToken(mToken);
      
           // True = successful token acquisition; False = failure
           return true;
      }
      
  3. Opcionalmente, use F6 (Build Solution) para executar uma compilação/link de teste da sua solução, para garantir que ela seja compilada com êxito antes de continuar.

Agora crie uma implementação para um delegado de consentimento estendendo a classe do mip::ConsentDelegate SDK e sobreescrevendo ou implementando a mip::AuthDelegate::GetUserConsent() função puramente virtual. O perfil de ficheiro e os objetos do motor de ficheiros instanciam e usam o delegado de consentimento mais tarde.

  1. Usando o mesmo recurso "Adicionar classe" do Visual Studio que usamos anteriormente, adicione outra classe ao seu projeto. Desta vez, digite "consent_delegate" no campo Nome da classe .

  2. Agora, atualize cada arquivo para implementar sua nova classe de delegado de consentimento:

    • Atualize "consent_delegate.h", substituindo todo o código de classe gerado consent_delegate pela seguinte fonte. Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include):

      #include "mip/common_types.h"
      #include <string>
      
      class ConsentDelegateImpl final : public mip::ConsentDelegate {
      public:
           ConsentDelegateImpl() = default;
           virtual mip::Consent GetUserConsent(const std::string& url) override;
      };
      
    • Atualize "consent_delegate.cpp", substituindo toda a implementação da classe gerada consent_delegate pelo seguinte código-fonte. Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include).

      #include <iostream>
      using mip::Consent;
      using std::string;
      
      Consent ConsentDelegateImpl::GetUserConsent(const string& url) 
      {
           // Accept the consent to connect to the url
           std::cout << "SDK will connect to: " << url << std::endl;
           return Consent::AcceptAlways;
      }
      
  3. Opcionalmente, use F6 (Build Solution) para executar uma compilação/link de teste da sua solução, para garantir que ela seja compilada com êxito antes de continuar.

Construir um perfil de arquivo e um motor

Como mencionado, os clientes SDK que usam APIs MIP requerem objetos de perfil e motor. Complete a parte de codificação deste quickstart adicionando código para instanciar os objetos do perfil e do motor:

  1. No Gerenciador de Soluções, abra o arquivo de .cpp em seu projeto que contém a main() implementação do método. Por padrão, tem o mesmo nome do projeto que o contém, que especificou durante a criação do projeto.

  2. Remova a implementação gerada do main(). Não remova diretivas de pré-processador geradas pelo Visual Studio durante a criação do projeto (#pragma, #include). Anexe o seguinte código após quaisquer diretivas de pré-processador:

#include "mip/mip_context.h"  
#include "auth_delegate.h"
#include "consent_delegate.h"
#include "profile_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::FileProfile;
using mip::FileEngine;

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>"};

  // Create MipConfiguration object.
  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<ProfileObserver>();                     // 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
  FileProfile::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<FileProfile>>>();
  auto profileFuture = profilePromise->get_future();

  try
	  { 
		  mip::FileProfile::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
  FileEngine::Settings engineSettings(
                                  mip::Identity("<engine-account>"), // Engine identity (account used for authentication)
                                  authDelegateImpl,		       // Token acquisition implementation
				    "<engine-state>",                  // User-defined engine state
                                  "en-US");                          // Locale (default = en-US)
                                  
  // Set the engineId for caching. 
  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<FileEngine>>>();
  auto engineFuture = enginePromise->get_future();
  profile->AddEngineAsync(engineSettings, enginePromise);
  std::shared_ptr<FileEngine> 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.
  // handler = nullptr; // This will be used in later quick starts.
  engine = nullptr;
  profile = nullptr;   
  mMipContext->ShutDown();
  mMipContext = nullptr;

  return 0;
  }
  1. Substitua todos os valores provisórios no código-fonte que colou usando constantes de string:

    Placeholder Value Exemplo
    <ID do aplicativo> O ID da aplicação Microsoft Entra (GUID) atribuído à aplicação registada no passo #2 do artigo "Instalação e configuração do SDK do MIP". Substitua 2 instâncias. "00001111-aaaa-2222-bbbb-3333cccc4444"
    <nome-aplicativo> Um nome amigável definido pelo usuário para seu aplicativo. Deve conter caracteres ASCII válidos (excluindo ';') e, idealmente, corresponde ao nome do aplicativo que você usou em seu registro do Microsoft Entra. "AppInitialization"
    <versão da aplicação> Informações de versão definidas pelo usuário para seu aplicativo. Deve conter caracteres ASCII válidos (excluindo ';'). "1.1.0.0"
    <conta de motor> A conta usada para a identidade do mecanismo. Quando você se autentica com uma conta de usuário durante a aquisição do token, ela deve corresponder a esse valor. "user1@tenant.onmicrosoft.com"
    <estado do motor> Estado definido pelo usuário a ser associado ao mecanismo. "My App State"
  2. Faz uma build final da aplicação e resolve quaisquer erros. O teu código deve compilar com sucesso, mas ainda não corre corretamente. Não tens um token de acesso para fornecer até completares o próximo quickstart.

Passos seguintes

Agora que o seu código de inicialização está completo, está pronto para o próximo quickstart, onde começa a experienciar os SDKs de ficheiros MIP.