快速入門:用戶端應用程式初始化 (C++)
本快速入門說明如何在執行時間實作 MIP C++ SDK 所使用的用戶端初始化模式。
注意
使用 MIP 檔案、原則或保護 SDK 的任何用戶端應用程式都需要本快速入門中所述的步驟。 雖然本快速入門示範檔案 SDK 的使用方式,但這個相同的模式適用于使用原則和保護 SDK 的用戶端。 依序完成其餘的快速入門,因為每個快速入門都以上一個快速入門為基礎,而此快速入門是第一個。
必要條件
如果您尚未這麼做,請務必:
- 完成 Microsoft 資訊保護 (MIP) SDK 設定和 設定中的 步驟。 本「用戶端應用程式初始化」快速入門依賴適當的 SDK 安裝和設定。
- 選擇:
建立 Visual Studio 方案和專案
首先,我們會建立並設定初始的 Visual Studio 方案和專案,而其他快速入門會建置。
開啟 Visual Studio 2017,選取 [ 檔案 ] 功能表 [ 新增 ]、[ 專案 ]。 在 [ 新增專案] 對話方塊中:
將 MIP 檔案 SDK 的 Nuget 套件新增至您的專案:
實作觀察者類別來監視檔案設定檔和引擎物件
現在,藉由擴充 SDK 的 類別,為檔案設定檔觀察者類別建立基本實作 mip::FileProfile::Observer
。 觀察者會具現化及稍後使用,以監視檔案設定檔物件的載入,並將引擎物件新增至設定檔。
將新類別新增至您的專案,這會為您產生標頭/.h 和 implementation/.cpp 檔案:
產生 類別的 .h 和 .cpp 檔案之後,這兩個檔案都會在 [編輯器群組] 索引標籤中開啟。 現在更新每個檔案以實作新的觀察者類別:
選取/刪除產生的
profile_observer
類別,以更新 「profile_observer.h」。 請勿 移除上一個步驟所產生的預處理器指示詞(#pragma、#include)。 然後在任何現有的預處理器指示詞之後,將下列來源複製/貼到檔案中:#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; };
選取/刪除產生的
profile_observer
類別實作,以更新 「profile_observer.cpp」。 請勿 移除上一個步驟所產生的預處理器指示詞(#pragma、#include)。 然後在任何現有的預處理器指示詞之後,將下列來源複製/貼到檔案中:#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); }
您可以選擇性地使用 F6 ( 建置方案 ) 來執行解決方案的測試編譯/連結,以確保它成功建置,然後再繼續。
實作驗證委派
MIP SDK 會使用類別擴充性來實作驗證,以提供與用戶端應用程式共用驗證工作的機制。 用戶端必須取得適當的 OAuth2 存取權杖,並在執行時間提供給 MIP SDK。
現在,藉由擴充 SDK 的 mip::AuthDelegate
類別,以及覆寫/實作純虛擬函式,來建立驗證委派的 mip::AuthDelegate::AcquireOAuth2Token()
實作。 驗證委派會由檔案設定檔和檔案引擎物件具現化及稍後使用。
使用我們在上一節的步驟 #1 中使用的相同 Visual Studio「新增類別」功能,將另一個類別新增至您的專案。 這次,請在 [類別名稱 ] 欄位中輸入 「auth_delegate」。
現在更新每個檔案,以實作新的驗證委派類別:
以下列來源取代所有產生的
auth_delegate
類別程式碼,以更新 「auth_delegate.h」。 請勿 移除上一個步驟所產生的預處理器指示詞(#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; };
以下列來源取代所有產生的
auth_delegate
類別實作,以更新 「auth_delegate.cpp」。 請勿 移除上一個步驟所產生的預處理器指示詞(#pragma、#include)。重要
下列權杖擷取程式碼不適合用于生產環境。 在生產環境中,必須使用下列專案,以動態方式取得權杖的程式碼來取代:
- Microsoft Entra 應用程式註冊中指定的 appId 和回復/重新導向 URI(回復/重新導向 URI 必須 符合您的應用程式註冊)
- SDK 在引數中
challenge
傳遞的授權單位和資源 URL(資源 URL 必須 符合您應用程式註冊的 API/許可權) - 有效的應用程式/使用者認證,其中帳戶符合
identity
SDK 所傳遞的引數。 OAuth2「原生」用戶端應該提示輸入使用者認證,並使用「授權碼」流程。 OAuth2「機密用戶端」可以使用自己的安全認證搭配「用戶端認證」流程(例如服務),或使用「授權碼」流程提示使用者認證(例如 Web 應用程式)。
OAuth2 權杖擷取是複雜的通訊協定,通常使用程式庫來完成。 TokenAcquireOAuth2Token() 只會 視需要由 MIP SDK 呼叫 。
#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; }
您可以選擇性地使用 F6 ( 建置方案 ) 來執行解決方案的測試編譯/連結,以確保它成功建置,然後再繼續。
實作同意委派
現在,藉由擴充 SDK 的 mip::ConsentDelegate
類別,以及覆寫/實 mip::AuthDelegate::GetUserConsent()
作純虛擬函式,建立同意委派的實作。 檔案設定檔和檔案引擎物件稍後會具現化並使用同意委派。
使用我們先前使用的相同 Visual Studio「新增類別」功能,將另一個類別新增至您的專案。 這次,在 [類別名稱 ] 欄位中輸入 「consent_delegate」。
現在更新每個檔案,以實作新的同意委派類別:
以下列來源取代所有產生的
consent_delegate
類別程式碼,以更新 「consent_delegate.h」。 請勿 移除上一個步驟所產生的預處理器指示詞(#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; };
以下列來源取代所有產生的
consent_delegate
類別實作,以更新 「consent_delegate.cpp」。 請勿 移除上一個步驟所產生的預處理器指示詞(#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; }
您可以選擇性地使用 F6 ( 建置方案 ) 來執行解決方案的測試編譯/連結,以確保它成功建置,然後再繼續。
建構檔案設定檔和引擎
如前所述,使用 MIP API 的 SDK 用戶端需要設定檔和引擎物件。 藉由新增程式碼來具現化設定檔和引擎物件,以完成本快速入門的程式碼部分:
從 方案總管 ,開啟專案中包含 方法實作的
main()
.cpp 檔案。 它預設為與您在專案建立期間指定的專案相同名稱。移除 產生的 實作
main()
。 請勿 在專案建立期間移除 Visual Studio 所產生的預處理器指示詞(#pragma,#include)。 在任何預處理器指示詞之後附加下列程式碼:
#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;
}
使用字串常數取代您剛貼上原始程式碼中的所有預留位置值:
預留位置 值 範例 <application-id> 指派給「MIP SDK 設定和設定」一文步驟 2 中 註冊之應用程式的 Microsoft Entra 應用程式識別碼(GUID)。 取代 2 個實例。 "0edbblll-8773-44de-b87c-b8c6276d41eb"
<application-name> 應用程式的使用者定義易記名稱。 必須包含有效的 ASCII 字元(不包括 ';'),而且最好符合您在 Microsoft Entra 註冊中使用的應用程式名稱。 "AppInitialization"
<application-version> 應用程式的使用者定義版本資訊。 必須包含有效的 ASCII 字元(不包括 ';')。 "1.1.0.0"
<engine-account> 用於引擎身分識別的帳戶。 當您在權杖擷取期間向使用者帳戶進行驗證時,它必須符合此值。 "user1@tenant.onmicrosoft.com"
<engine-state> 要與引擎相關聯的使用者定義狀態。 "My App State"
現在請執行應用程式的最終組建,並解決任何錯誤。 您的程式碼應該會順利建置,但在您完成下一個快速入門之前,尚未正確執行。 如果您執行應用程式,您會看到類似下列的輸出。 在您完成下一個快速入門之前,您不會提供存取權杖。
後續步驟
現在您的初始化程式碼已完成,您已準備好進行下一個快速入門,您將開始體驗 MIP 檔案 SDK。