快速入门 - 使用文件 SDK 初始化 MIP SDK C++ 客户端

快速入门 - 使用文件 SDK 初始化 MIP SDK C++ 客户端

本快速入门介绍如何在运行时实现 MIP C++ SDK 使用的客户端初始化模式。

注释

使用 MIP 文件、策略或保护 SDK 的任何客户端应用程序都需要本快速入门中所述的步骤。 尽管本快速入门演示了文件 SDK 的使用,但此模式同样适用于使用策略和保护 SDK 的客户端。 请按照顺序完成剩余的快速入门,因为每一个都建立在上一个的基础上,而这个是第一个。

先决条件

如果尚未这样做,请确保:

完成 Microsoft信息保护 (MIP) SDK 设置和配置中的步骤。 本“客户端应用程序初始化”快速入门依赖于正确的 SDK 设置和配置。

可选:

查看 配置文件和引擎对象。 配置文件和引擎对象是使用 MIP 文件/策略/保护 SDK 的客户端所需的通用概念。

查看 身份验证概念 ,了解 SDK 和客户端应用程序如何实现身份验证和同意。

查看 观察者概念 ,详细了解观察程序及其实现方式。 MIP SDK 使用观察程序模式实现异步事件通知。

创建 Visual Studio 解决方案和项目

首先,我们创建并配置初始 Visual Studio 解决方案和项目,其他快速入门将基于该解决方案和项目进行生成。

打开 Visual Studio 2019 或更高版本,选择 “文件 ”菜单“ 新建”和 “项目”。 在 “新建项目 ”对话框中:

在左窗格中的 “已安装”下,选择“ 其他语言”,选择 “视觉对象C++。

在中心窗格中,选择 Windows 控制台应用程序

在底部窗格中,相应地更新项目 名称、 位置和包含 的解决方案名称 。

完成后,单击右下角的 “确定 ”按钮。

将 MIP 文件 SDK 的 NuGet 包添加到项目:

在 解决方案资源管理器中,右键单击项目节点(直接在顶部/解决方案节点下),然后选择“ 管理 NuGet 包...”:

当编辑器组选项卡区域打开 NuGet 包管理器 选项卡时:

选择“浏览”。

在搜索框中输入“Microsoft.InformationProtection”。

选择“Microsoft.InformationProtection.File”包。

单击“安装”,然后在 “预览”更改 确认对话框显示时单击“确定”。

实现观察程序类来监视文件配置文件和引擎对象

现在,通过扩展 SDK 的 mip::FileProfile::Observer 类,为文件描述观察者类创建一个基本实现。 观察程序将实例化,稍后再用于监视文件配置文件对象的加载,以及将引擎对象添加到配置文件。

将新类添加到项目,这将会生成 header/.h 和 implementation/.cpp 文件:

在“解决方案资源管理器”中,再次右键单击项目节点,选择“添加”,然后选择“类”。

在 “添加类 ”对话框中:

在 “类名 ”字段中,输入“profile_observer”。 请注意,系统会根据输入的名称自动填充“.h 文件”和“.cpp 文件”字段。

完成后,单击“确定”按钮。

为类生成 .h 文件和 .cpp 文件后,这两个文件都会在编辑器组选项卡中打开。 现在更新每个文件,实现新的观察程序类:

通过选择/删除生成的 profile_observer 类来更新“profile_observer.h”。

不要删除上一步生成的预处理器指令(#pragma、#include)。 然后,将以下源复制/粘贴到文件中的任何现有预处理器指令之后:

#include

#include "mip/file/file_profile.h"

class ProfileObserver final : public mip::FileProfile::Observer {

public:

ProfileObserver() { }

void OnLoadSuccess(const std::shared_ptr& profile, const std::shared_ptr& context) override;

void OnLoadFailure(const std::exception_ptr& error, const std::shared_ptr& context) override;

void OnAddEngineSuccess(const std::shared_ptr& engine, const std::shared_ptr& context) override;

void OnAddEngineFailure(const std::exception_ptr& error, const std::shared_ptr& context) override;

};

通过选择/删除生成的 profile_observer 类实现来更新“profile_observer.cpp”。

不要删除上一步生成的预处理器指令(#pragma、#include)。 然后,将以下源复制/粘贴到文件中的任何现有预处理器指令之后:

#include

using std::promise;

using std::shared_ptr;

using std::static_pointer_cast;

using mip::FileEngine;

using mip::FileProfile;

void ProfileObserver::OnLoadSuccess(const shared_ptr& profile, const shared_ptr& context) {

auto promise = static_pointer_cast>>(context);

promise->set_value(profile);

}

void ProfileObserver::OnLoadFailure(const std::exception_ptr& error, const shared_ptr& context) {

auto promise = static_pointer_cast>>(context);

promise->set_exception(error);

}

void ProfileObserver::OnAddEngineSuccess(const shared_ptr& engine, const shared_ptr& context) {

auto promise = static_pointer_cast>>(context);

promise->set_value(engine);

}

void ProfileObserver::OnAddEngineFailure(const std::exception_ptr& error, const shared_ptr& context) {

auto promise = static_pointer_cast>>(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

#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/权限匹配)

有效的应用/用户凭据,其中帐户与 SDK 传递的参数匹配 identity 。 OAuth2“本地”客户端应提示输入用户凭据并使用“获取授权代码”流程。 OAuth2“机密客户端”可以通过“客户端凭据”流(例如服务)使用自己的安全凭据,或通过“授权代码”流(例如 Web 应用)提示输入用户凭据。

OAuth2 令牌获取是一种复杂的协议,通常通过使用库来完成。 根据需要,TokenAcquireOAuth2Token() 仅由 MIP SDK 调用。

#include

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(生成解决方案)运行解决方案的测试编译/链接,以确保在继续之前成功完成生成。

实现许可委托

现在,通过扩展软件开发工具包的 mip::ConsentDelegate 类,并重写或实现 mip::AuthDelegate::GetUserConsent() 纯虚拟函数,创建一个授权委托的实现。 许可委托稍后由文件配置文件和文件引擎对象实例化并使用。

使用以前使用的同一 Visual Studio“添加类”功能,将另一个类添加到项目中。 这一次,在 “类名 ”字段中输入“consent_delegate”。

现在更新每个文件以实现新的同意委托类:

通过将生成的所有consent_delegate类代码替换为以下源代码,更新“consent_delegate.h”。

请勿 删除上一步生成的预处理器指令(#pragma,#include):

#include "mip/common_types.h"

#include

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

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{"",

"",

""};

// Create MipConfiguration object.

std::shared_ptr mipConfiguration = std::make_shared(appInfo,

"mip_data",

mip::LogLevel::Trace,

false);

std::shared_ptr mMipContext = mip::MipContext::Create(mipConfiguration);

auto profileObserver = make_shared(); // Observer object

auto authDelegateImpl = make_shared(""); // Authentication delegate object (App ID)

auto consentDelegateImpl = make_shared(); // 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>>();

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 identity (account used for authentication)

authDelegateImpl, // Token acquisition implementation

"", // User-defined engine state

"en-US"); // Locale (default = en-US)

// Set the engineId for caching.

engineSettings.SetEngineId("");

// Set up promise/future connection for async engine operations; add engine to profile asynchronously

auto enginePromise = make_shared>>();

auto engineFuture = enginePromise->get_future();

profile->AddEngineAsync(engineSettings, enginePromise);

std::shared_ptr 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;

}

使用字符串常量替换刚刚粘贴的源代码中的所有占位符值:

占位符

价值

示例:

分配给在 MIP SDK 安装和配置一文的步骤 #2 中注册的应用程序的 Microsoft Entra 应用程序 ID (GUID)。 替换 2 个实例。

"0edbblll-8773-44de-b87c-b8c6276d41eb"

<应用程序名称>

您的应用程序的自定义友好名称。 必须包含有效的 ASCII 字符(不包括“;”),并且理想情况下与在 Microsoft Entra 注册中使用的应用程序名称匹配。

"AppInitialization"

<应用程序版本>

应用程序的用户定义的版本信息。 必须包含有效的 ASCII 字符(不包括“;”)。

"1.1.0.0"

<引擎账户>

用于引擎标识的帐户。 在获取令牌期间使用用户帐户进行身份验证时,它必须与此值匹配。

"user1@tenant.onmicrosoft.com"

<引擎状态>

与引擎关联的用户定义的状态。

"My App State"

现在,构建应用程序的最终版本并解决任何错误。 代码可以成功编译,然而在完成下一个快速开始之前,代码仍无法正确运行。 如果运行应用程序,则会看到如下所示的输出。 在完成下一个快速入门之前,你将无法提供访问令牌。

后续步骤

完成初始化代码后,接下来可以开始学习下一个快速入门,你将开始了解 MIP 文件 SDK。

列出敏感度标签

相关推荐

一头驴大概多少钱,一头驴多少钱一只
mobile365-777

一头驴大概多少钱,一头驴多少钱一只

📅 07-22 👁️ 2479
《我的世界》网页版入口一览
mobile365-777

《我的世界》网页版入口一览

📅 07-27 👁️ 6268
余额宝为什么限购“瘦身”?
365bet网上手机投注

余额宝为什么限购“瘦身”?

📅 07-17 👁️ 9931
三星n7108d最新报价「三星n7108d」
mobile365-777

三星n7108d最新报价「三星n7108d」

📅 08-23 👁️ 2676
兰州公交各类乘车卡充值、挂失、补办、退卡指南
365bet网上手机投注

兰州公交各类乘车卡充值、挂失、补办、退卡指南

📅 07-23 👁️ 7940