Snabbstart: Initiering av klientprogram (C++)
Den här snabbstarten visar hur du implementerar mönstret för klientinitiering som används av MIP C++ SDK vid körning.
Kommentar
De steg som beskrivs i den här snabbstarten krävs för alla klientprogram som använder SDK:er för MIP-filer, principer eller skydd. Även om den här snabbstarten visar hur fil-SDK:erna används, gäller samma mönster för klienter som använder SDK:er för princip och skydd. Slutför de återstående snabbstarterna seriellt, eftersom var och en bygger på den föregående, där den här är den första.
Förutsättningar
Om du inte redan har gjort det måste du:
- Slutför stegen i Konfiguration och konfiguration av Microsoft Information Protection (MIP) SDK. Den här snabbstarten "Klientprograminitiering" förlitar sig på korrekt SDK-konfiguration.
- Valfritt:
- Granska profil- och motorobjekt. Profil- och motorobjekten är universella begrepp som krävs av klienter som använder SDK:er för MIP-fil/princip/skydd.
- Läs Autentiseringsbegrepp för att lära dig hur autentisering och medgivande implementeras av SDK och klientprogrammet.
- Läs Observer-begrepp för att lära dig mer om observatörer och hur de implementeras. MIP SDK använder övervakningsmönstret för att implementera asynkrona händelsemeddelanden.
Skapa en Visual Studio-lösning och ett projekt
Först skapar och konfigurerar vi den första Visual Studio-lösningen och projektet, som de andra snabbstarterna bygger på.
Öppna Visual Studio 2017, välj menyn Arkiv , Nytt, Projekt. I dialogrutan Nytt projekt:
Lägg till Nuget-paketet för MIP File SDK i projektet:
I Solution Explorer högerklickar du på projektnoden (direkt under den övre noden/lösningsnoden) och väljer Hantera NuGet-paket...:
När fliken NuGet Package Manager öppnas i området Redigerargruppflikar:
- Välj bläddra.
- Ange "Microsoft.InformationProtection" i sökrutan.
- Välj paketet "Microsoft.InformationProtection.File".
- Klicka på "Installera" och sedan på "OK" när bekräftelsedialogrutan Förhandsgranskningsändringar visas.
Implementera en observatörsklass för att övervaka objekten Filprofil och motor
Skapa nu en grundläggande implementering för en filprofilobservatörsklass genom att utöka SDK:ts mip::FileProfile::Observer
klass. Observatören instansieras och används senare för att övervaka inläsningen av filprofilobjektet och lägga till motorobjektet i profilen.
Lägg till en ny klass i projektet, som genererar både huvud-/.h- och implementeringsfilerna/.cpp åt dig:
I Solution Explorer högerklickar du på projektnoden igen, väljer Lägg till och väljer sedan Klass.
I dialogrutan Lägg till klass:
- I fältet Klassnamn anger du "profile_observer". Observera att både .h-filen och .cpp-filfälten fylls i automatiskt, baserat på det namn du anger.
- När du är klar klickar du på ok-knappen .
När du har genererat .h- och .cpp-filerna för klassen öppnas båda filerna på flikarna Redigerargrupp. Uppdatera nu varje fil för att implementera din nya observatörsklass:
Uppdatera "profile_observer.h" genom att välja/ta bort den genererade
profile_observer
klassen. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#pragma, #include). Kopiera/klistra sedan in följande källa i filen efter befintliga förprocessordirektiv:#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; };
Uppdatera "profile_observer.cpp" genom att välja/ta bort den genererade
profile_observer
klassimplementeringen. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#pragma, #include). Kopiera/klistra sedan in följande källa i filen efter befintliga förprocessordirektiv:#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); }
Du kan också använda F6 (Build Solution) för att köra en testkompilering/länk för din lösning för att se till att den skapas korrekt innan du fortsätter.
Implementera en autentiseringsdelegat
MIP SDK implementerar autentisering med hjälp av utökningsbarhet för klassen, vilket ger en mekanism för att dela autentiseringsarbete med klientprogrammet. Klienten måste hämta en lämplig OAuth2-åtkomsttoken och tillhandahålla MIP SDK vid körning.
Skapa nu en implementering för ett autentiseringsdelegat genom att utöka SDK:ts mip::AuthDelegate
klass och åsidosätta/implementera den mip::AuthDelegate::AcquireOAuth2Token()
rena virtuella funktionen. Autentiseringsdelegaten instansieras och används senare av objekten Filprofil och Filmotor.
Med samma Visual Studio-funktion "Lägg till klass" som vi använde i steg 1 i föregående avsnitt lägger du till ytterligare en klass i projektet. Den här gången anger du "auth_delegate" i fältet Klassnamn .
Uppdatera nu varje fil för att implementera din nya autentiseringsdelegatklass:
Uppdatera "auth_delegate.h" genom att ersätta all genererad
auth_delegate
klasskod med följande källa. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#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; };
Uppdatera "auth_delegate.cpp" genom att ersätta all genererad
auth_delegate
klassimplementering med följande källa. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#pragma, #include).Viktigt!
Följande tokeninsamlingskod är inte lämplig för produktionsanvändning. I produktion måste detta ersättas med kod som dynamiskt hämtar en token med hjälp av:
- AppId och svars-/omdirigerings-URI som anges i din Microsoft Entra-appregistrering (svars-/omdirigerings-URI måste matcha din appregistrering)
- Utfärdaren och resurs-URL:en som skickades av SDK:n i
challenge
argumentet (resurs-URL:en måste matcha appregistreringens API/behörigheter) - Giltiga autentiseringsuppgifter för app/användare, där kontot matchar argumentet
identity
som skickas av SDK:t. OAuth2-klienter bör fråga efter användarautentiseringsuppgifter och använda flödet "auktoriseringskod". OAuth2 "konfidentiella klienter" kan använda sina egna säkra autentiseringsuppgifter med flödet "klientautentiseringsuppgifter" (till exempel en tjänst) eller fråga efter användarautentiseringsuppgifter med hjälp av flödet "auktoriseringskod" (till exempel en webbapp).
OAuth2-tokenförvärv är ett komplext protokoll som normalt utförs med hjälp av ett bibliotek. TokenAcquireOAuth2Token() anropas endast av MIP SDK efter behov.
#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; }
Du kan också använda F6 (Build Solution) för att köra en testkompilering/länk för din lösning för att se till att den skapas korrekt innan du fortsätter.
Implementera en medgivandedelegat
Skapa nu en implementering för ett medgivandedelegat genom att utöka SDK:ts mip::ConsentDelegate
klass och åsidosätta/implementera den mip::AuthDelegate::GetUserConsent()
rena virtuella funktionen. Medgivandedelegaten instansieras och används senare av objekten Filprofil och Filmotor.
Med samma Visual Studio-funktion "Lägg till klass" som vi använde tidigare lägger du till en annan klass i projektet. Den här gången anger du "consent_delegate" i fältet Klassnamn .
Uppdatera nu varje fil för att implementera din nya medgivandedelegatklass:
Uppdatera "consent_delegate.h" genom att ersätta all genererad
consent_delegate
klasskod med följande källa. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#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; };
Uppdatera "consent_delegate.cpp" genom att ersätta all genererad
consent_delegate
klassimplementering med följande källa. Ta inte bort de förprocessordirektiv som genererades av föregående steg (#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; }
Du kan också använda F6 (Build Solution) för att köra en testkompilering/länk för din lösning för att se till att den skapas korrekt innan du fortsätter.
Skapa en filprofil och motor
Som nämnts krävs profil- och motorobjekt för SDK-klienter med hjälp av MIP-API:er. Slutför kodningsdelen av den här snabbstarten genom att lägga till kod för att instansiera profil- och motorobjekten:
Öppna .cpp-filen i projektet som innehåller implementeringen av
main()
metoden från Solution Explorer. Det är som standard samma namn som det projekt som innehåller det, som du angav när projektet skapades.Ta bort den genererade implementeringen av
main()
. Ta inte bort förprocessordirektiv som genereras av Visual Studio när projektet skapas (#pragma, #include). Lägg till följande kod efter eventuella förprocessordirektiv:
#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;
}
Ersätt alla platshållarvärden i källkoden som du precis klistrade in med hjälp av strängkonstanter:
Platshållare Värde Exempel <application-id> Microsoft Entra-program-ID (GUID) som tilldelats det program som registrerats i steg 2 i artikeln "Konfiguration och konfiguration av MIP SDK" . Ersätt 2 instanser. "0edbblll-8773-44de-b87c-b8c6276d41eb"
<programnamn> Ett användardefinierat eget namn för ditt program. Måste innehålla giltiga ASCII-tecken (exklusive ';') och matchar helst det programnamn som du använde i din Microsoft Entra-registrering. "AppInitialization"
<programversion> Användardefinierad versionsinformation för ditt program. Måste innehålla giltiga ASCII-tecken (exklusive ';'). "1.1.0.0"
<engine-account> Det konto som används för motorns identitet. När du autentiserar med ett användarkonto under tokenförvärvet måste det matcha det här värdet. "user1@tenant.onmicrosoft.com"
<motortillstånd> Användardefinierat tillstånd som ska associeras med motorn. "My App State"
Gör nu en slutlig version av programmet och lös eventuella fel. Koden bör byggas korrekt, men den kommer inte att köras korrekt förrän du har slutfört nästa snabbstart. Om du kör programmet visas utdata som liknar följande. Du har ingen åtkomsttoken att ange förrän du har slutfört nästa snabbstart.
Nästa steg
Nu när initieringskoden är klar är du redo för nästa snabbstart, där du börjar uppleva MIP-fil-SDK:erna.