Microsoft 信息保护 SDK - 文件处理程序引擎概念

在 MIP 文件 SDK 中,mip::FileHandler 公开可用于在内置了支持的一组文件类型中读取和写入标签或保护的各种操作。

支持的文件类型

  • 基于 OPC 的 Office 文件格式(Office 2010 及更高版本)
  • 旧版 Office 文件格式(Office 2007)
  • PDF
  • 通用 PFILE 支持
  • 支持 Adobe XMP 的文件

文件处理程序函数

mip::FileHandler 公开用于读取、写入和移除标签和保护信息的方法。 有关完整列表,请参阅 API 参考

本文将介绍以下方法:

  • GetLabelAsync()
  • SetLabel()
  • DeleteLabel()
  • RemoveProtection()
  • CommitAsync()

要求

要创建要用于特定文件的 FileHandler,需要满足以下条件:

  • 执行 FileProfile 操作
  • 添加到 FileProfileFileEngine
  • 继承 mip::FileHandler::Observer 的类

创建文件处理程序

在文件 SDK 中管理任何文件所需的第一步是创建 FileHandler 对象。 该类用于实现获取、设置、更新、删除和提交文件的标签更改所需的所有功能。

FileHandler 的创建与使用承诺/未来模式调用 FileEngineCreateFileHandlerAsync 函数一样简单。

CreateFileHandlerAsync 接受三个参数:应读取或修改的文件的路径、异步事件通知的 mip::FileHandler::Observer,以及 FileHandler 的承诺。

注意:mip::FileHandler::Observer 类必须在派生类中实现,因为 CreateFileHandler 需要 Observer 对象。

auto createFileHandlerPromise = std::make_shared<std::promise<std::shared_ptr<mip::FileHandler>>>();
auto createFileHandlerFuture = createFileHandlerPromise->get_future();
fileEngine->CreateFileHandlerAsync(filePath, std::make_shared<FileHandlerObserver>(), createFileHandlerPromise);
auto fileHandler = createFileHandlerFuture.get();

成功创建 FileHandler 对象后,可以执行文件操作(获取/设置/删除/提交)。

读取标签

元数据要求

要求从文件成功读取元数据并将其转换为可在应用程序中使用的内容,需要满足一些要求。

  • 要读取的标签必须仍存在于 Microsoft 365 服务中。 如果已将其完全删除,SDK 将无法获取有关该标签的信息,并返回错误。
  • 文件元数据必须完好。 此元数据包括:
    • Attribute1
    • Attribute2

GetLabelAsync()

创建处理程序以指向特定文件后,我们将返回承诺/未来模式以异步读取标签。 此承诺适用于 mip::ContentLabel 对象,其中包含所应用标签的所有信息。

实例化 promisefuture 对象后,我们将通过调用 fileHandler->GetLabelAsync() 并提供作为单一参数的 promise 来读取标签。 最后,标签可以存储在我们将从 future 中获取的 mip::ContentLabel 对象中。

auto loadPromise = std::make_shared<std::promise<std::shared_ptr<mip::ContentLabel>>>();
auto loadFuture = loadPromise->get_future();
fileHandler->GetLabelAsync(loadPromise);
auto label = loadFuture.get();

可以从 label 对象中读取标签数据并将其传递到应用程序中的任何其他组件或功能。


设置标签

设置标签的过程由两个部分组成。 首先,在创建了指向相关文件的处理程序之后,可以通过调用带有某些参数(mip::Labelmip::LabelingOptionsmip::ProtectionOptions)的 FileHandler->SetLabel() 来设置标签。 首先,我们必须将标签 ID 解析为标签,然后定义标签选项。

将标签 ID 解析为 mip::Label

SetLabel 函数的第一个参数是 mip::Label。 通常,应用程序使用的是标签标识符,而不是标签。 可以通过在文件或策略引擎上调用 GetLabelById 来将标签标识符解析为 mip::Label

mip::Label label = mEngine->GetLabelById(labelId);

标签选项

设置标签所需的第二个参数是 mip::LabelingOptions

LabelingOptions 用于指定有关标签的其他信息,例如 AssignmentMethod 和操作的理由。

  • mip::AssignmentMethod 是具有三个值的枚举器:STANDARDPRIVILEGEDAUTO。 查看 mip::AssignmentMethod 参考以了解更多详细信息。
  • 仅在服务策略要求填写并且降低文件的“现有”敏感度时才需要填写理由。

此截图演示如何创建 mip::LabelingOptions 对象并设置降级理由和消息。

auto labelingOptions = mip::LabelingOptions(mip::AssignmentMethod::STANDARD);
labelingOptions.SetDowngradeJustification(true, "Because I made an educated decision based upon the contents of this file.");

保护设置

某些应用程序可能需要代表委托用户标识执行操作。 通过 mip::ProtectionSettings 类,应用程序可以定义每个处理程序的委托标识。 以前,委托操作是由引擎类执行的。 这在应用程序开销和服务往返方面有很大的弊端。 通过将委托用户设置移动到 mip::ProtectionSettings 并使之成为处理程序类的一部分,我们消除了这一开销,从而为代表各种用户标识执行许多操作的应用程序提供更好的性能。

如果不需要委派,则将 mip::ProtectionSettings() 传递给 SetLabel 函数。 如果需要委托,则可以通过创建 mip::ProtectionSettings 对象并设置委托邮件地址来实现此目的:

mip::ProtectionSettings protectionSettings; 
protectionSettings.SetDelegatedUserEmail("alice@contoso.com");

设置标签

在使用 ID 中提取了 mip::Label,设置好标签选项,并(可选)设置好保护设置后,现在可以在处理程序上设置标签。

如果未设置保护设置,请通过在处理程序上调用 SetLabel 来设置标签:

fileHandler->SetLabel(label, labelingOptions, mip::ProtectionSettings());

如果需要保护设置来执行委托操作,则执行以下操作:

fileHandler->SetLabel(label, labelingOptions, protectionSettings);

现已在处理程序引用的文件上设置好标签,不过还需要完成另外一个步骤才能提交更改并将文件写入磁盘或创建输出流。

提交更改

要在 MIP SDK 中提交对文件的任何更改,最后一步是“提交”该更改。 这是通过使用 FileHandler->CommitAsync() 函数来实现的。

为了实现承诺函数,我们会返回承诺/未来模式为 bool 创建承诺。 如果操作成功,CommitAsync() 函数将返回 true;如果操作因任何原因失败,则返回 false。

创建 promisefuture 后,将调用 CommitAsync() 并提供两个参数:输出文件路径 (std::string) 和承诺。 最后,通过获取 future 对象的值来获取结果。

auto commitPromise = std::make_shared<std::promise<bool>>();
auto commitFuture = commitPromise->get_future();
fileHandler->CommitAsync(outputFile, commitPromise);
auto wasCommitted = commitFuture.get();

重要提示:FileHandler 不会更新或覆盖现有的文件。 要“替换”正在标记的文件,将由开发人员来实现。

如果将标签写入 FileA.docx,则会使用应用的标签创建该文件的副本 FileB.docx。 必须编写代码来移除/重命名 FileA.docx 并重命名 FileB.docx


删除标签

auto fileHandler = mEngine->CreateFileHandler(filePath, std::make_shared<FileHandlerObserverImpl>());
fileHandler->DeleteLabel(mip::AssignmentMethod::PRIVILEGED, "Label unnecessary.");
auto commitPromise = std::make_shared<std::promise<bool>>();
auto commitFuture = commitPromise->get_future();
fileHandler->CommitAsync(outputFile, commitPromise);

删除保护

MIP 文件 SDK 应用程序必须验证用户是否有权从正在访问的文件中移除保护。 这可以通过在移除保护之前执行访问权限检查来实现。

RemoveProtection() 函数的行为方式类似于 SetLabel()DeleteLabel()。 该方法在现有的 FileHandler 对象上调用,然后必须提交更改。

重要

应用程序开发人员负责执行此访问权限检查。 如果未正确执行访问权限检查,可能会导致数据泄漏。

C++ 示例:

// Validate that the file referred to by the FileHandler is protected.
if (fileHandler->GetProtection() != nullptr)
{
    // Validate that user is allowed to remove protection.
    if (fileHandler->GetProtection()->AccessCheck(mip::rights::Export() || fileHandler->GetProtection()->AccessCheck(mip::rights::Owner()))
    {
        auto commitPromise = std::make_shared<std::promise<bool>>();
        auto commitFuture = commitPromise->get_future();
        // Remove protection and commit changes to file.
        fileHandler->RemoveProtection();
        fileHandler->CommitAsync(outputFile, commitPromise);
        result = commitFuture.get();
    }
    else
    {
        // Throw an exception if the user doesn't have rights to remove protection.
        throw std::runtime_error("User doesn't have EXPORT or OWNER right.");
    }
}

.NET 示例:

if(handler.Protection != null)
{                
    // Validate that user has rights to remove protection from the file.                    
    if(handler.Protection.AccessCheck(Rights.Extract) || handler.Protection.AccessCheck(Rights.Owner))
    {
        // If user has Extract right, remove protection and commit the change. Otherwise, throw exception. 
        handler.RemoveProtection();
        bool result = handler.CommitAsync(outputPath).GetAwaiter().GetResult();     
        return result;   
    }
    else
    {
        throw new Microsoft.InformationProtection.Exceptions.AccessDeniedException("User lacks EXPORT right.");
    }
}