Guia de início rápido: inicialização do aplicativo cliente (C++)
Este guia de início rápido mostra como implementar o padrão de inicialização do cliente, usado pelo MIP C++ SDK em tempo de execução.
Nota
As etapas descritas neste início rápido são necessárias para qualquer aplicativo cliente que use o arquivo MIP, a política ou os SDKs de proteção. Embora este Guia de início rápido demonstre o uso dos SDKs de arquivo, esse mesmo padrão é aplicável aos clientes que usam os SDKs de política e proteção. Complete os restantes Quickstarts em série, à medida que cada um se baseia no anterior, sendo este o primeiro.
Pré-requisitos
Se ainda não o fez, certifique-se de:
- Conclua as etapas na instalação e configuração do SDK do Microsoft Information Protection (MIP). Este Guia de início rápido de "inicialização do aplicativo cliente" depende da instalação e configuração adequadas do SDK.
- Opcionalmente:
- Revise os objetos do perfil e do mecanismo. Os objetos de perfil e mecanismo são conceitos universais, exigidos por clientes que usam os SDKs de arquivo/política/proteção MIP.
- Analise os conceitos de autenticação para saber como a autenticação e o consentimento são implementados pelo SDK e pelo aplicativo cliente.
- Analise os conceitos do Observer para saber mais sobre os observadores e como eles são implementados. O MIP SDK usa o padrão de observador para implementar notificações de eventos assíncronas.
Criar uma solução e um projeto do Visual Studio
Primeiro, criamos e configuramos a solução e o projeto iniciais do Visual Studio, sobre os quais os outros Quickstarts são compilados.
Abra o Visual Studio 2017, selecione o menu Arquivo , Novo, Projeto. Na caixa de diálogo Novo projeto:
Adicione o pacote Nuget para o MIP File SDK 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 Gerenciador de Pacotes NuGet for aberta na área de guias 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.
Implementar uma classe de observador para monitorar o perfil File e os objetos do mecanismo
Agora, crie uma implementação básica para uma classe de observador de perfil de arquivo, estendendo a classe do mip::FileProfile::Observer
SDK. O observador é instanciado e usado posteriormente, para monitorar o carregamento do objeto de perfil File e adicionar o objeto Engine ao perfil.
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 .
Depois de gerar os arquivos .h e .cpp para a classe, ambos os arquivos são abertos nas guias Grupo de Editores. 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); }
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 MIP SDK implementa a autenticação usando extensibilidade de classe, que fornece um mecanismo para compartilhar o trabalho de autenticação com o aplicativo cliente. O cliente deve adquirir um token de acesso OAuth2 adequado e fornecer 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 substituindo/implementando a função virtual pura mip::AuthDelegate::AcquireOAuth2Token()
. O delegado de autenticação é instanciado e usado posteriormente, pelos objetos File profile e File engine.
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.
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 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; };
Atualize "auth_delegate.cpp", substituindo toda a implementação de classe gerada
auth_delegate
pela seguinte fonte. Não remova as diretivas de pré-processador geradas pela etapa anterior (#pragma, #include).Importante
O código de aquisição de token a seguir não é adequado para uso em produção. Na produção, isso deve ser substituído por um código que adquire dinamicamente um token, usando:
- 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 deve corresponder à API/permissões do registro do
challenge
aplicativo) - Credenciais válidas de aplicativo/usuário, onde a conta corresponde ao
identity
argumento passado pelo SDK. Os clientes "nativos" do 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 realizado usando 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, 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; }
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 consentimento
Agora, crie uma implementação para um delegado de consentimento, estendendo a classe do mip::ConsentDelegate
SDK e substituindo/implementando a função virtual pura mip::AuthDelegate::GetUserConsent()
. O delegado de consentimento é instanciado e usado posteriormente, pelos objetos File profile e File engine.
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.
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 de classe gerada
consent_delegate
pela seguinte 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; }
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 mecanismo
Como mencionado, os objetos de perfil e mecanismo são necessários para clientes SDK que usam APIs MIP. Conclua a parte de codificação deste Guia de início rápido, adicionando código para instanciar os objetos de perfil e mecanismo:
No Gerenciador de Soluções, abra o arquivo de .cpp em seu projeto que contém a
main()
implementação do método. O padrão é o mesmo nome do projeto que o contém, que você especificou durante a criação do projeto.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);
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;
}
Substitua todos os valores de espaço reservado no código-fonte que você acabou de colar, usando constantes de cadeia de caracteres:
Marcador de Posição Valor Exemplo <ID do aplicativo> O Microsoft Entra Application ID (GUID) atribuído ao aplicativo registrado na etapa #2 do artigo "MIP SDK setup and configuration". Substitua 2 instâncias. "0edbblll-8773-44de-b87c-b8c6276d41eb"
<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"
<aplicação-versã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-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-motor> Estado definido pelo usuário a ser associado ao mecanismo. "My App State"
Agora faça uma compilação final do aplicativo e resolva quaisquer erros. Seu código deve ser compilado com êxito, mas ainda não será executado corretamente até que você conclua o próximo Guia de início rápido. Se você executar o aplicativo, verá uma saída semelhante à seguinte. Você não terá um token de acesso para fornecer até concluir o próximo Guia de início rápido.
Passos Seguintes
Agora que o código de inicialização está concluído, você está pronto para o próximo início rápido, onde começará a experimentar os SDKs de arquivo MIP.