Compartir a través de


Inicio rápido: Inicialización de aplicaciones cliente (C++)

En este inicio rápido se muestra cómo implementar el patrón de inicialización de cliente, usado por el SDK de C++ de MIP en tiempo de ejecución.

Nota:

Los pasos descritos en este inicio rápido son necesarios para cualquier aplicación cliente que use los SDK de archivo, directiva o protección de MIP. Aunque en esta guía de inicio rápido se muestra el uso de los SDK de archivo, este mismo patrón se aplica a los clientes que usan los SDK de directiva y protección. Complete los inicios rápidos restantes en serie, ya que cada uno se basa en el anterior, siendo éste el primero.

Prerrequisitos

Si aún no lo ha hecho, asegúrese de:

  • Complete los pasos descritos en Configuración y configuración del SDK de Microsoft Information Protection (MIP). Este Quickstart de "Inicialización de aplicaciones cliente" se basa en la configuración y ajuste adecuados del SDK.
  • Opcionalmente:
    • Revise Objetos de perfil y motor. Los objetos de perfil y motor son conceptos universales, requeridos por los clientes que usan los SDK de archivo/política/protección de MIP.
    • Revise Conceptos de autenticación para obtener información sobre cómo el SDK y la aplicación cliente implementan la autenticación y el consentimiento.
    • Revise los conceptos de Observer para obtener más información sobre los observadores y cómo se implementan. El SDK de MIP usa el patrón de observador para implementar notificaciones de eventos asincrónicas.

Creación de una solución y un proyecto de Visual Studio

En primer lugar, creamos y configuramos la solución y el proyecto iniciales de Visual Studio, en los que se compilan las otras guías de inicio rápido.

  1. Abra Visual Studio 2019 o posterior, seleccione el menú Archivo , Nuevo, Proyecto. En el cuadro de diálogo Nuevo proyecto

    • En el panel izquierdo, en Instalado, Otros lenguajes, seleccione Visual C++.

    • En el panel central, seleccione Aplicación de consola de Windows.

    • En el panel inferior, actualice el nombre del proyecto, la ubicación y el nombre de la solución contenedora en consecuencia.

    • Cuando termine, haga clic en el botón Aceptar en la parte inferior derecha.

      Creación de soluciones de Visual Studio

  2. Agregue el paquete NuGet para el SDK de archivos MIP al proyecto:

    • En el Explorador de soluciones, haga clic con el botón derecho en el nodo del proyecto (directamente en el nodo superior o solución) y seleccione Administrar paquetes NuGet...:

    • Cuando se abra la pestaña Administrador de paquetes NuGet en el área de pestañas del grupo de editores:

      • Selecciona Examinar.
      • Escriba "Microsoft.InformationProtection" en el cuadro de búsqueda.
      • Seleccione el paquete "Microsoft.InformationProtection.File".
      • Haga clic en "Instalar" y, a continuación, haga clic en "Aceptar" cuando se muestre el cuadro de diálogo de confirmación Vista previa de cambios .

      Agregar paquete NuGet de Visual Studio

Implementa una clase de observador para supervisar el perfil de archivos y los objetos del motor de archivos

Ahora cree una implementación básica para una clase de observador de perfil de archivo mediante la extensión de la clase del mip::FileProfile::Observer SDK. Se crea una instancia del observador que después se usa para supervisar la carga del objeto de perfil de archivo y la incorporación del objeto de motor en el perfil.

  1. Agregue una nueva clase al proyecto, que genera los archivos header/.h e implementation/.cpp automáticamente:

    • En el Explorador de soluciones, haga clic con el botón derecho en el nodo del proyecto de nuevo, seleccione Agregar y, a continuación, seleccione Clase.

    • En el cuadro de diálogo Agregar clase:

      • En el campo Nombre de clase, escriba "profile_observer". Tenga en cuenta que tanto el archivo .h como los campos de archivo .cpp se rellenan automáticamente, en función del nombre que escriba.
      • Cuando termine, haga clic en el botón Aceptar .

      Añadir clase en Visual Studio

  2. Después de generar los archivos .h y .cpp para la clase , ambos archivos se abren en las pestañas Grupo de editores. Ahora actualice cada archivo para implementar la nueva clase de observador:

    • Actualice "profile_observer.h", seleccionando o eliminando la clase generada profile_observer . No quite las directivas de preprocesador generadas por el paso anterior (#pragma, #include). A continuación, copie y pegue el siguiente código fuente en el archivo, después de las directivas de preprocesador que ya existan:

      #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;
      };
      
    • Actualice "profile_observer.cpp", seleccionando o eliminando la implementación de clase generada profile_observer . No quite las directivas de preprocesador generadas por el paso anterior (#pragma, #include). A continuación, copie y pegue el siguiente código fuente en el archivo, después de las directivas de preprocesador que ya existan:

      #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 (Compilar solución) para ejecutar una compilación o vínculo de prueba de la solución, para asegurarse de que se compila correctamente antes de continuar.

Implementación de un delegado de autenticación

El SDK de MIP implementa la autenticación mediante la extensibilidad de clases, que proporciona un mecanismo para compartir el trabajo de autenticación con la aplicación cliente. El cliente debe adquirir un token de acceso de OAuth2 adecuado y proporcionar al SDK de MIP en tiempo de ejecución.

Ahora cree una implementación para un delegado de autenticación, ampliando la clase del mip::AuthDelegate SDK y reemplazando o implementando la mip::AuthDelegate::AcquireOAuth2Token() función virtual pura. Se crea una instancia del delegado de autenticación, que después usan los objetos de perfil de archivo y de motor de archivo.

  1. Con la misma característica de Visual Studio "Agregar clase" que usamos en el paso 1 de la sección anterior, agregue otra clase al proyecto. Esta vez, escriba "auth_delegate" en el campo Nombre de clase.

  2. Ahora actualice cada archivo para implementar la nueva clase de delegado de autenticación:

    • Actualice "auth_delegate.h", reemplazando todo el código de clase generado auth_delegate por el siguiente origen. No quite las directivas de preprocesador generadas por el paso 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 AAD 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 (AAD tenant issuing token), and resource (API being accessed; "aud" claim).
             OAuth2Token& token) override;     // Token handed back to MIP SDK
      
      private:
           std::string mAppId;
           std::string mToken;
           std::string mAuthority;
           std::string mResource;
      };
      
    • Actualice "auth_delegate.cpp", reemplazando toda la implementación de clase generada auth_delegate por el siguiente origen. No quite las directivas de preprocesador generadas por el paso anterior (#pragma, #include).

      Importante

      El siguiente código de adquisición de tokens no es adecuado para su uso en producción. En producción, debe reemplazarse por código que adquiere dinámicamente un token mediante:

      • El identificador de aplicación y el URI de respuesta/redirección especificados en el registro de aplicaciones de Microsoft Entra (el URI de respuesta o redirección debe coincidir con el registro de la aplicación).
      • La autoridad y el URL del recurso que el SDK pasa en el argumento challenge (el URL del recurso debe coincidir con la API o los permisos del registro de tu aplicación).
      • Credenciales de usuario o aplicación válidas, donde la cuenta coincide con el identity argumento pasado por el SDK. Los clientes "nativos" de OAuth2 deben solicitar credenciales de usuario y usar el flujo de "código de autorización". OAuth2 "clientes confidenciales" pueden usar sus propias credenciales seguras con el flujo de "credenciales de cliente" (por ejemplo, un servicio) o solicitar credenciales de usuario mediante el flujo de "código de autorización" (como una aplicación web).

      La adquisición de tokens de OAuth2 es un protocolo complejo y normalmente se logra mediante una biblioteca. A TokenAcquireOAuth2Token() solo lo llama el SDK de MIP, según sea necesario.

      #include <iostream>
      using std::cout;
      using std::cin;
      using std::string;
      
      bool AuthDelegateImpl::AcquireOAuth2Token(const mip::Identity& identity, const OAuth2Challenge& challenge, OAuth2Token& token) 
      {
           // 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 (Compilar solución) para ejecutar una compilación o vínculo de prueba de la solución, para asegurarse de que se compila correctamente antes de continuar.

Ahora cree una implementación para un delegado de consentimiento, ampliando la clase del mip::ConsentDelegate SDK y reemplazando o implementando la mip::AuthDelegate::GetUserConsent() función virtual pura. Se crea una instancia del delegado de consentimiento, que después usan los objetos de perfil de archivo y de motor de archivo.

  1. Con la misma característica de Visual Studio "Agregar clase" que usamos anteriormente, agregue otra clase al proyecto. Esta vez, escriba "consent_delegate" en el campo Nombre de clase .

  2. Ahora actualice cada archivo para implementar la nueva clase de delegado de consentimiento:

    • Actualice "consent_delegate.h", reemplazando todo el código de clase generado consent_delegate por el siguiente origen. No quite las directivas de preprocesador generadas por el paso 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;
      };
      
    • Actualice "consent_delegate.cpp", reemplazando todas las implementaciones de clase generadas consent_delegate por la siguiente fuente. No quite las directivas de preprocesador generadas por el paso 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 (Compilar solución) para ejecutar una compilación o vínculo de prueba de la solución, para asegurarse de que se compila correctamente antes de continuar.

Creación de un motor y un perfil de archivo

Como se mencionó, los objetos de perfil y motor son necesarios para los clientes del SDK que usan API de MIP. Complete la parte de codificación de este inicio rápido agregando código para crear instancias de los objetos de perfil y motor:

  1. En el Explorador de soluciones, abra el archivo .cpp en el proyecto que contiene la implementación del main() método . El valor predeterminado es el mismo nombre que el proyecto que lo contiene, que especificó durante la creación del proyecto.

  2. Quite la implementación generada de main(). No elimine las directivas de preprocesador generadas por Visual Studio durante la creación del proyecto (#pragma, #include). Anexe el código siguiente después de cualquier directiva de preprocesador:

#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);


  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. Reemplace todos los valores de marcador de posición en el código fuente que acaba de pegar, mediante constantes de cadena:

    Marcador de posición Valor Ejemplo
    <application-id> El identificador de aplicación (GUID) de Microsoft Entra asignado a la aplicación registrada en el paso 2 del artículo "Configuración y configuración del SDK de MIP ". Reemplace ambas instancias. "0edbblll-8773-44de-b87c-b8c6276d41eb"
    <nombre de aplicación> Nombre fácil de reconocer definido por el usuario para su aplicación. Debe contener caracteres ASCII válidos (excepto ';') y lo ideal es que coincida con el nombre de la aplicación que usó en el registro de Microsoft Entra. "AppInitialization"
    <versión de la aplicación> Información de versión definida por el usuario para la aplicación. Debe contener caracteres ASCII válidos (excepto ';'). "1.1.0.0"
    <engine-account> Cuenta usada para la identidad del motor. Cuando se autentique con una cuenta de usuario durante la adquisición de tokens, debe coincidir con este valor. "user1@tenant.onmicrosoft.com"
    <estado del motor> Estado definido por el usuario que se va a asociar al motor. "My App State"
  2. Ahora realice una compilación final de la aplicación y resuelva los errores. El código debe compilarse correctamente, pero aún no se ejecutará correctamente hasta completar el siguiente inicio rápido. Si ejecuta la aplicación, verá una salida similar a la siguiente. No tendrá un token de acceso para proporcionar, hasta que complete el siguiente inicio rápido.

Pasos siguientes

Ahora que tu código de inicialización está completo, estás listo para el siguiente Quickstart, donde comenzarás a trabajar con los SDK de MIP File.