适用于 Android 的 Intune App SDK - 多标识

Microsoft Intune App SDK for Android 允许将 Intune 应用保护策略 (也称为 APP 或 MAM 策略) 合并到本机 Java/Kotlin Android 应用中。 Intune 托管的应用程序是与 Intune 应用 SDK 集成的应用程序。 当 Intune 主动管理应用时,Intune 管理员可以轻松地将应用保护策略部署到 Intune 托管的应用。

注意

本指南分为几个不同的阶段。 首先查看 第 1 阶段:规划集成

阶段 5:多标识

阶段Goals

  • 确定应用程序是否需要多标识支持。
  • 了解 Intune 应用 SDK 如何感知标识。
  • 重构应用程序以增强标识意识。
  • 添加代码以在整个应用程序中通知 SDK 活动标识和不断变化的标识。
  • 全面测试托管和非托管标识的应用保护策略强制实施。

标识术语

术语“user”、“account”和“identity”通常可互换使用。 本指南尝试按如下所示进行区分:

  • 用户:使用软件产品的人。 进一步区分为最终用户、使用 Android 应用的人和管理员 / 用户 / IT / 专业人员(使用 Microsoft Intune 管理中心的人)。
  • 帐户:属于唯一标识用户实体的组织的软件记录。 一个用户可以有多个帐户。
  • 标识:Intune 应用 SDK 用于唯一标识帐户的数据集。

背景

默认情况下,Intune App SDK 将策略应用于整个应用程序。 使用面向的应用保护策略注册帐户后,SDK 会将每个文件和每个活动与该帐户的标识相关联,并将普遍应用该帐户的目标策略。

对于许多开发人员来说,这是其应用程序所需的应用保护行为。 这些应用程序被视为 单一标识。 通过完成前面的阶段,应用程序已成功集成为单一标识,并且可以强制实施所有基本策略。 旨在保持单一标识的应用可以跳过此部分,继续执行第 6 阶段:应用程序配置

Intune App SDK 可以选择在每个标识级别强制实施策略。 如果应用程序已支持同时登录的多个帐户,并且你希望通过应用保护策略保留此多帐户支持,则应用程序被视为 多标识

提示

如果不清楚应用程序是否应支持单标识或多标识保护,请重新访问 我的应用程序是单一标识还是多标识?

警告

支持多标识比其他应用保护功能要复杂得多。 不正确地集成多标识可能会导致数据泄漏和其他安全问题。 在继续下一阶段之前,请仔细查看此部分并计划充足的测试时间。

SDK 的“标识”

当 SDK 集成应用程序使用 registerAccountForMAM 注册帐户时,SDK 会将提供的所有参数 (upn、aadId、tenantId 和 authority) 保存为标识。 但是,大多数 SDK 的标识 API 仅使用提供的 upn 字符串作为标识的简写。 这些 API 将仅返回 upn 字符串作为标识,并且仅需要标识的 upn 字符串参数。

标识不区分大小写。 对 SDK 的标识请求可能不会返回注册或设置标识时使用的相同大小写。

提示

将来,SDK API 可能会提供更全面的标识结构,其中包括在帐户注册时提供的所有字段,而不仅仅是 upn。 集成多标识支持时,请确保应用在使用当前 API 设置标识时也有权访问 aadId、tenantId 和颁发机构。

托管标识与非托管标识

注册应用保护策略中所述,应用程序负责在用户登录时通知 SDK。 在登录时,用户的帐户可能成为也可能不是应用保护策略的目标。 如果帐户是应用保护策略的目标,则 SDK 会将其视为托管;否则,它是非托管的。

SDK 将对其认为托管的标识强制实施策略。 SDK 不会对认为非托管的标识强制实施策略。

目前,Intune App SDK 仅支持每个设备一个托管标识。 任何 SDK 集成的应用程序注册托管标识后,所有随后注册的标识(即使它们当前是应用保护策略的目标)都将被视为非托管标识。

如果已在设备上注册托管标识,并且你的应用注册了另一个同样面向应用保护策略的标识,则 SDK 将返回 MAMEnrollmentManager.Result.WRONG_USER 并提示最终用户提供修正选项。 有关更多详细信息 ,请参阅从 SDK 注册通知

注意

在注册时未使用应用保护策略的帐户将被视为非托管帐户。 即使帐户未获得应用保护策略的许可或目标,SDK 也会定期检查,如果以后此帐户获得许可并成为目标。 如果尚未注册其他托管标识,则 SDK 在将其作为策略目标后,将开始将此标识视为托管标识。 用户无需注销并重新登录到此帐户即可进行此更改。

活动标识

应用程序必须始终将当前使用的标识(也称为活动标识)通知 SDK。 如果活动标识是托管的,则 SDK 将应用保护。 如果活动标识不受管理,则 SDK 不会应用保护。

由于 SDK 没有特定于应用程序的知识,因此它必须信任应用程序来共享正确的活动标识。

  • 如果应用程序错误地告知 SDK 非托管标识在实际使用时处于活动状态,则 SDK 不会应用保护。 这可能会导致数据泄漏,使用户的数据面临风险。

  • 如果应用程序错误地告知 SDK 托管标识在实际使用非托管标识时处于活动状态,则 SDK 将不恰当地应用保护。 这不是数据泄漏,但可能会不必要地限制非托管用户,并使非托管用户的数据面临删除风险。

如果应用程序显示任何用户的数据,则它必须仅显示属于活动标识的数据。 如果应用程序当前不知道谁拥有显示的数据,则可能需要在开始集成多标识支持之前重构应用程序以增强标识意识。

按标识组织应用数据

每当应用程序写入新文件时,SDK 会根据当前活动线程和进程标识将 (也称为“标记”) 标识与该文件相关联。 或者,应用可以直接调用 SDK 来手动标记具有特定标识的文件 (请参阅 编写受保护的文件 了解详细信息) 。 SDK 使用此标记的文件标识进行文件加密和选择性擦除。

如果托管标识是加密策略的目标,则只会加密使用托管标识标记的文件。

如果管理员操作或配置的策略请求已擦除托管数据,将仅删除使用托管标识标记的文件。

SDK 无法将多个标识与单个文件相关联。 如果应用将属于多个用户的数据存储在同一文件中,则 SDK 的默认行为将导致此数据保护不足或过度保护。 强烈建议你按标识组织应用的数据

如果应用绝对必须将属于不同标识的数据存储在同一文件中,则 SDK 提供用于对文件中数据子集进行标识标记的功能。 有关详细信息 ,请参阅数据缓冲区保护

实现多标识

若要为应用声明多标识支持,请首先在 AndroidManifest.xml 中放置以下元数据。

  <meta-data
    android:name="com.microsoft.intune.mam.MAMMultiIdentity"
    android:value="true" />

设置活动标识

应用程序可以按降序优先级在以下级别设置活动标识:

  1. 线程级别
  2. Context (通常 Activity) 级别
  3. 进程级别

在线程级别设置的标识取代在级别设置 Context 的标识,后者取代在进程级别设置的标识。

Context 设置的标识仅在适当的关联方案中使用。 例如,文件 IO 操作没有关联的 Context。 最常见的是,应用会在 上Activity设置Context标识。 考虑在 ContextActivity.onCreate设置标识。 除非标识设置为同一标识,Activity否则应用不得显示标识的数据。

通常,仅当应用在所有线程上一次仅处理单个标识时,进程级标识才有用。 对于支持多个帐户的应用,这不是典型行为。 强烈建议隔离帐户数据,并在线程或 Context 级别上设置活动标识。

如果你的应用使用 Application 上下文来获取系统服务,请确保已设置线程或进程标识,或者你已在应用的 Application 上下文中设置了 UI 标识。

如果你的应用使用 Service 上下文来启动意向、使用内容解析程序或利用其他系统服务,请确保在上下文中 Service 设置标识。 同样,如果你的应用使用JobService上下文来执行这些操作,请确保根据实现的要求JobServiceJobService上下文或线程上设置标识。 例如,如果 JobService 处理单个标识的作业,请考虑在上下文中 JobService 设置标识。 JobService如果处理多个标识的作业,请考虑在线程级别设置标识。

警告

使用 WorkManager 的应用在设置标识时应特别小心。 具体而言,这些应用应避免在构造函数中传递的 WorkerContext设置标识。 此 Context 实例可以同时在多个 Worker 实例之间共享。 若要避免未定义的行为,应用应改为在 中 Worker.doWork() 设置实现所需的 Worker 线程标识。

注意

CLIPBOARD_SERVICE由于 用于 UI 操作,因此 SDK 使用前台活动的 UI 标识进行ClipboardManager操作。

MAMPolicyManager 中的以下方法可用于设置活动标识并检索以前设置的标识值。

public static void setUIPolicyIdentity(final Context context, final String identity, final MAMSetUIIdentityCallback mamSetUIIdentityCallback,
final EnumSet<IdentitySwitchOption> options);

public static String getUIPolicyIdentity(final Context context);

public static MAMIdentitySwitchResult setProcessIdentity(final String identity);

public static String getProcessIdentity();

public static MAMIdentitySwitchResult setCurrentThreadIdentity(final String identity);

public static String getCurrentThreadIdentity();

/**
 * Get the current app policy. This does NOT take the UI (Context) identity into account.
 * If the current operation has any context (e.g. an Activity) associated with it, use the overload below.
 */
public static AppPolicy getCurrentThreadPolicy();

/**
 * Get the current app policy. This DOES take the UI (Context) identity into account.
 * If the current operation has any context (e.g. an Activity) associated with it, use this function.
 */
public static AppPolicy getPolicy(final Context context);


public static AppPolicy getPolicyForIdentity(final String identity);

public static boolean getIsIdentityManaged(final String identity);

为方便起见,还可以通过 MAMActivity 中的方法直接设置活动的标识,而不是调用 MAMPolicyManager.setUIPolicyIdentity。 使用以下方法执行此操作:

     public final void switchMAMIdentity(final String newIdentity, final EnumSet<IdentitySwitchOption> options);

注意

如果你的应用未在清单中声明多标识支持,则调用这些方法来设置标识将不会执行任何操作,如果它们返回 , MAMIdentitySwitchResult将始终返回 FAILED

常见标识切换陷阱

  • 对于对 startActivity的调用,Intune App SDK 假定级别的 Context 活动标识与提供 Intent 的参数相关联。 强烈建议使用 Activity的上下文(而不是 Application的上下文)设置Context级别标识。

  • 建议在 Context Activity 的 onCreate 方法期间设置标识。 但是,请务必同时涵盖其他入口点,例如 onNewIntent。 否则,当重复使用同一活动来显示托管和非托管标识的数据时,策略可能会被错误地应用,从而导致公司数据不受保护或个人数据受到不当限制。

标识切换结果

用于通过 MAMIdentitySwitchResult 设置标识报告结果值的所有方法。 可以返回四个值:

返回值 应用场景
SUCCEEDED 标识更改成功。
NOT_ALLOWED 不允许更改标识。 如果在当前线程上设置其他标识时,尝试设置 UI (Context) 标识,则会发生这种情况。
CANCELLED 用户取消了标识更改,通常是通过按 PIN 或身份验证提示符上的后退按钮。
FAILED 由于未指定的原因,标识更改失败。

应用应在显示或使用托管帐户的数据之前验证 MAMIdentitySwitchResultSUCCEEDED

设置活动标识的大多数方法同步返回 MAMIdentitySwitchResult 。 在通过 setUIPolicyIdentity 设置Context标识的情况下,将异步报告结果。 应用可以实现 MAMSetUIIdentityCallback 来接收此结果,或者可能会为回调对象传递 null。 如果在同一setUIPolicyIdentity上下文上一次调用setUIPolicyIdentity的结果尚未传递时调用 ,则新回调将取代旧回调,而原始回调将永远不会收到结果。

警告

Context如果提供给 setUIPolicyIdentity 的 是 ,Activity则 SDK 在执行管理员配置的条件启动检查之前,不知道标识更改是否成功。 这可能需要用户输入 PIN 或公司凭据。

目前,对于启用了多标识的应用,进程和线程标识切换将始终成功。 SDK 保留将来添加故障条件的权利。

如果 UI 标识开关与线程标识冲突,或者如果用户取消了条件启动要求(例如, (按 PIN 屏幕上的后退按钮) ),则 UI 标识开关可能会失败。

活动上失败的 UI 标识开关的默认行为是完成活动。 若要更改此行为并接收有关活动的标识更改尝试的通知,可以在 中 MAMActivity替代 方法。

    public void onSwitchMAMIdentityComplete(final MAMIdentitySwitchResult result);

如果替代 onSwitchMAMIdentityComplete (或) 调用 super 方法, 则必须 确保在标识切换失败后不会显示托管帐户的数据。

注意

切换标识可能需要重新创建活动。 在这种情况下,回调 onSwitchMAMIdentityComplete 将传递到活动的新实例。

Identity、Intents 和 IdentitySwitchOptions

除了使用活动标识自动标记新文件外,SDK 还使用活动标识标记 意向 。 默认情况下,SDK 将对传入意向检查标识,并将其与活动标识进行比较。 如果这些标识不匹配,SDK 通常会 (*) 请求标识切换 (请参阅下面的 隐式标识更改 ,了解) 的更多详细信息。

SDK 还存储此传入意向标识,供以后使用。 当应用显式更改 UI 标识时,SDK 会将应用尝试切换到的标识与最新的传入意向标识进行比较。 如果这些标识不匹配,SDK 通常会 (*) 标识切换失败。

SDK 执行此检查,因为它假定应用仍显示来自意向的内容,该意向属于在意向上标记的标识。 此假设可防止应用在显示托管数据时意外关闭保护;但是,此假设可能与应用的实际行为不一定正确。

可以将可选的 IdentitySwitchOption 枚举传递给 setUIPolicyIdentityswitchMAMIdentity API,以修改 SDK 的默认行为。

  • IGNORE_INTENT:在 UI 层请求标识开关时,此选项会通知 SDK 跳过将请求的标识参数与最近存储的意向标识进行比较。 当应用不再显示属于该标识的内容,并且 SDK 不应阻止此标识切换时,这很有用。 例如:

    1. 你的应用是文档查看器。 它可以呈现从其他应用传入的文档。 它还包含一项功能,用户可以在其中切换帐户。 每当用户使用此帐户切换功能时,应用将导航到具有该帐户最近文档的特定于帐户的登陆页面。
    2. 应用收到显示文档的意向。 此意向使用托管标识进行标记。
    3. 应用将切换到托管标识并显示此文档,并正确应用了保护。
    4. 用户使用帐户切换器更改其个人帐户。

    你的应用必须在步骤 4 中更改 UI 标识。 在这种情况下,由于应用的行为是在意向) 中从托管帐户的数据 (文档中导航,因此应在标识切换调用中使用 IGNORE_INTENT 。 这可避免 SDK 错误地失败此调用。

  • DATA_FROM_INTENT:在 UI 层请求标识切换时,此选项会通知 SDK,在标识 切换成功后,将继续显示最近存储的意向标识中的数据。 因此,SDK 将针对以前的意向标识全面评估接收策略,以确定是否允许显示它。 例如:

    1. 你的应用是文档查看器。 它可以呈现从其他应用传入的文档。 它还包含一项功能,用户可以在其中切换帐户。 与前面的示例不同,每当用户使用此帐户切换功能时,应用都会导航到显示 所有帐户的最新文档的共享页面。
    2. 应用收到显示文档的意向。 此意向使用托管标识进行标记。
    3. 应用将切换到托管标识并显示此文档,并正确应用了保护。
    4. 用户使用帐户切换器更改其个人帐户。

    你的应用必须在步骤 4 中更改 UI 标识。 在这种情况下,由于应用的行为是在意向) 中继续显示托管标识的数据 (文档预览,因此应在标识切换调用中使用 DATA_FROM_INTENT 。 这会通知 SDK 检查配置的应用保护策略,以确定它是否适合继续显示数据。

(*) SDK 的默认行为包括跳过此数据入口 检查的特殊大小写,例如,如果意向来自同一应用内部或系统启动器,则跳过此数据入口。

清除活动标识

应用程序可能具有与帐户无关的方案。 应用程序可能还具有不需要任何登录的本地非托管方案的方案。 在这两种情况下,你的应用可能不希望 SDK 强制实施托管标识的策略,但你可能没有要切换到的显式标识。

可以通过调用将标识参数设置为 null的任意设置标识方法来清除活动标识。 在一个级别清除标识将导致 SDK 根据优先级顺序在其他级别查找活动标识。

或者,可以将空字符串作为标识参数传递,这将标识设置为一个特殊的空值,该值被视为非托管标识。 将活动标识设置为空字符串会告知 SDK 不要强制实施 任何 应用保护策略。

隐式标识更改

以上部分介绍了应用在线程、上下文和进程级别显式设置活动标识的不同方式。 但是,应用中的活动标识也可以更改,而无需应用调用任何这些方法。 本部分介绍应用如何侦听和响应这些隐式标识更改。

侦听这些隐式标识更改是可选的,但建议这样做。 如果不提供这些隐式标识更改通知,SDK 永远不会更改活动标识。

警告

如果你的应用选择不侦听隐式标识更改,请格外小心,不要采用活动标识。 如果有任何疑问,请使用 getCurrentThreadIdentitygetUIPolicyIdentitygetProcessIdentity 方法来确认活动标识。

隐式标识更改的来源

  • 来自 其他 Intune 托管应用 的数据入口可以更改线程和上下文级别的活动标识。

    • 如果活动是从另一个 Intent MAM 应用发送的 启动的,则会根据发送 时其他应用中的活动标识来设置该 Intent 活动的标识。

      • 例如,当用户选择文档附件时,将从 Microsoft Outlook 的意向启动用于查看Word文档的活动。 Office 的文档查看器活动的标识从 Outlook 切换到标识。
    • 对于服务,线程标识将在 或 onBind 调用期间onStart以类似的方式设置。 Binder调用从 onBind 返回的 也将临时设置线程标识。

    • 对 的 ContentProvider 调用同样会设置线程标识的持续时间。

  • 用户 与活动的交互可以在上下文级别更改活动标识。 例如:

    • 用户取消授权提示期间 Resume 将导致隐式切换到空标识。

处理隐式标识更改

你的应用可以选择侦听这些隐式标识更改并做出响应。 例如,应用程序可能需要多个步骤才能使用添加的帐户,例如设置新收件箱的电子邮件应用。 看到尝试的标识切换到此不完整帐户的标识后,应用处理程序可以在接受标识切换之前将用户重定向到帐户设置活动。 或者,应用的处理程序可能会显示错误对话框并阻止标识开关。

你的应用可以在 或 ContextProviderService实现 MAMIdentityRequirementListener 接口,以便对应用于此线程的标识更改。 实现必须重写:

public abstract void onMAMIdentitySwitchRequired(String identity,
        AppIdentitySwitchResultCallback callback);

应用可以在 上实现 MAMActivityIdentityRequirementListener 接口 Activity ,以便对应用于此活动的标识更改。 实现必须重写:

public abstract void onMAMIdentitySwitchRequired(String identity,
        AppIdentitySwitchReason reason,
        AppIdentitySwitchResultCallback callback);

枚举 AppIdentitySwitchReason 参数描述隐式标识开关的源。

枚举值 默认 SDK 行为 说明
CREATE 允许标识切换。 由于活动创建,正在发生标识切换。
NEW_INTENT 允许标识切换。 正在发生标识切换,因为正在向活动分配新的意向。
RESUME_CANCELLED 阻止标识切换。 由于取消了恢复,因此发生了标识切换。 当最终用户按下 PIN、身份验证或合规性 UI 上的后退按钮时,这种情况最为常见。

AppIdentitySwitchResultCallback 参数允许开发人员替代标识开关的默认行为:

public interface AppIdentitySwitchResultCallback {
  /**
    * @param result
    *            whether the identity switch can proceed.
    */
  void reportIdentitySwitchResult(AppIdentitySwitchResult result);
}
// Where [AppIdentitySwitchResult] is either `SUCCESS` or `FAILURE`.

onMAMIdentitySwitchRequired 为所有隐式标识更改调用 ,但通过从 MAMService.onMAMBind返回的 Binder 进行的更改除外。 的默认实现 onMAMIdentitySwitchRequired 立即调用:

  • callback.reportIdentitySwitchResult(FAILURE) 当原因为 RESUME_CANCELLED时。

  • callback.reportIdentitySwitchResult(SUCCESS) 在所有其他情况下。

预计大多数应用不需要以其他方式阻止或延迟标识切换,但如果应用需要这样做,则必须考虑以下几点:

  • 如果标识开关被阻止,则最终用户行为与 SDK 的“从其他应用接收数据”应用保护设置禁止数据进入相同。

  • 如果服务在main线程上运行,reportIdentitySwitchResult则必须同步调用,否则 UI 线程停止响应。

  • 对于Activity创建,将在 之前onMAMCreate调用 onMAMIdentitySwitchRequired。 如果应用必须显示 UI 以确定是否允许标识切换,则必须使用 其他 活动显示该 UI。

  • 在 中 Activity,当请求切换到空标识且原因为 RESUME_CANCELLED时,应用必须修改恢复的活动,以显示与该标识开关一致的数据。 如果无法执行此操作,应用应拒绝切换,并且将再次要求用户遵守恢复标识 (的策略,例如,) 显示应用 PIN 输入屏幕。

警告

多标识应用可以从托管和非托管应用接收传入数据。 应用负责以托管方式处理来自托管标识的数据。

如果请求的标识是托管的 (使用 MAMPolicyManager.getIsIdentityManaged 检查) ,但应用无法使用该帐户 (例如,因为帐户(如电子邮件帐户)必须先在应用中设置) 则应拒绝标识切换。

可以通过调用静态方法 MAMActivity.defaultOnMAMIdentitySwitchRequired(activity, identity, reason, callback)来访问 的默认行为MAMActivity.onMAMIdentitySwitchRequired

同样,如果需要重写 MAMActivity.onSwitchMAMIdentityComplete,则可以在不显式继承自 MAMActivity的情况下实现 MAMActivityIdentitySwitchListener

标识切换和屏幕截图限制

Intune App SDK 使用 Window 标志 FLAG_SECURE 来强制实施屏幕截图策略。 某些应用也可能出于自己的目的而设置 FLAG_SECURE 。 当应用保护策略不限制屏幕截图时,SDK 不会修改 FLAG_SECURE

在标识从策略要求禁用屏幕截图的标识切换到策略不禁用的标识时,SDK 将清除 FLAG_SECURE。 因此,你的应用不应依赖于 FLAG_SECURE 标识切换后的剩余集。

在异步操作中保留标识

应用通常从 UI 线程调度后台任务,以处理其他线程上的操作。 多标识应用必须确保这些后台任务使用适当的标识进行操作,该标识通常是调度它们的活动使用的相同标识。

Intune 应用 SDK 提供 MAMAsyncTaskMAMIdentityExecutors ,以帮助在异步操作中保留标识。 如果应用的异步操作可以,则应用必须使用这些 (或显式设置任务上的线程标识) :

  • 将属于托管标识的数据写入文件
  • 与其他应用通信

MAMAsyncTask

若要使用 MAMAsyncTask,只需继承自它而不是 AsyncTask ,并将 的doInBackgroundonPreExecute替代分别替换为 doInBackgroundMAMonPreExecuteMAM 。 构造 MAMAsyncTask 函数采用活动上下文。 例如:

AsyncTask<Object, Object, Object> task = new MAMAsyncTask<Object, Object, Object>(thisActivity) {

    @Override
    protected Object doInBackgroundMAM(final Object[] params) {
        // Do operations.
    }

    @Override
    protected void onPreExecuteMAM() {
        // Do setup.
    };
}

MAMAsyncTask 将基于正常优先级顺序假定活动标识。

MAMIdentityExecutors

MAMIdentityExecutors允许使用 和 方法将现有 ExecutorExecutorService 实例包装为标识保留ExecutorService/ExecutorwrapExecutorwrapExecutorService 例如

Executor wrappedExecutor = MAMIdentityExecutors.wrapExecutor(originalExecutor, activity);
ExecutorService wrappedService = MAMIdentityExecutors.wrapExecutorService(originalExecutorService, activity);

MAMIdentityExecutors 将基于正常优先级顺序假定活动标识。

文件保护

写入受保护的文件

如上述 按标识组织应用数据 中所述,Intune 应用 SDK 会将线程/进程级别的活动标识 () 与写入文件时关联。 在文件创建时设置正确的标识以确保适当的加密和选择性擦除功能至关重要。

你的应用可以使用 MAMFileProtectionManager 类查询或更改文件的标识,专用 MAMFileProtectionManager.getProtectionInfo 于查询和 MAMFileProtectionManager.protect 更改。

方法 protect 还可用于保护目录。 目录保护以递归方式应用于目录中包含的所有文件和子目录。 当目录受到保护时,在该目录中创建的所有新文件将自动应用相同的保护。 由于目录保护以递归方式应用,因此对于大型目录, protect 调用可能需要一些时间才能完成。 因此,对包含大量文件的目录应用保护的应用可能希望在后台线程上异步运行 protect

调用 protect 标识参数的空字符串将使用非托管标识标记文件/目录。 如果以前已加密,此操作将从文件/目录中删除加密。 发出选择性擦除命令时,不会删除文件/目录。

显示受保护的文件内容

同样重要的是,在 显示 文件内容时设置正确的标识,以防止未经授权的用户查看托管数据。 SDK 无法自动推断正在读取的文件与 在 中显示的 Activity数据之间的关系。 在显示任何托管数据之前,应用 必须 正确设置 UI 标识。 这包括从文件读取的数据。

如果文件来自应用外部 (或 ContentProvider 从可公开写入位置读取) ,则应用 必须 尝试使用正确的 MAMFileProtectionManager.getProtectionInfo 重载确定文件标识 (数据源) ,然后才能显示从文件读取的信息。

如果 getProtectionInfo 报告非空的非空标识,应用 必须使用MAMActivity.switchMAMIdentityMAMPolicyManager.setUIPolicyIdentity 设置 UI 标识以匹配此标识。 如果标识切换失败,则 不得 显示文件中的数据。

从内容 URI 读取时,可能需要先通过 getProtectionInfo 采用) 的重载 Uri 来读取标识 (,然后相应地设置上下文或线程标识。 必须在 在 上 ContentResolver打开文件描述符或输入流之前完成此操作,否则操作可能会失败。

示例流可能如下所示:

  • 用户选择要在应用中打开的文档。

  • 在打开流期间,在从磁盘读取数据之前,应用会确认应用于显示内容的标识:

    MAMFileProtectionInfo info = MAMFileProtectionManager.getProtectionInfo(docPath)
    if (info != null)
        MAMPolicyManager.setUIPolicyIdentity(activity, info.getIdentity(), callback, EnumSet.noneOf<IdentitySwitchOption.class>)
    
  • 应用将等待,直到将结果报告给回调。

  • 如果报告的结果是失败,则应用不会显示文档。

  • 应用将打开并呈现文件。

如果应用使用 Android DownloadManager 下载文件,SDK 将尝试使用 前面所述的标识优先级自动保护这些文件。 如果未设置线程标识, DownloadManager 则将使用用于检索 的上下文。 如果下载的文件包含公司数据,则应用负责在下载后移动或重新创建文件时调用 protect

Single-Identity 到多标识转换

如果以前使用单标识 Intune 集成发布的应用后来集成了多标识,则以前安装的应用将经历转换。 此转换对用户不可见。

应用 不需要 处理此转换。 在转换之前创建的所有文件将继续被视为托管 (因此,如果加密策略处于) 上,它们将保持加密状态。

如果不希望所有以前的应用数据都与托管标识相关联,可以检测此转换并显式删除保护。

  • 通过将应用的版本与添加了多标识支持的已知版本进行比较来检测升级。
  • 对于不希望与托管标识关联的文件或目录,使用空字符串调用 protect 标识参数。

脱机方案

未安装 公司门户 应用时,Intune 应用 SDK 在“脱机”模式下运行。 文件标识标记对脱机模式敏感:

  • 如果未安装公司门户,则无法对文件进行标识标记。 在脱机模式下调用 MAMFileProtectionManager.protect 是安全的,但不起作用。

  • 如果已安装公司门户,但应用没有应用保护策略,则文件无法可靠地进行标识标记。

  • 文件标识标记可用时,以前创建的所有文件都被视为属于空字符串标识) 的个人/非托管 (,除非以前将应用安装为单标识托管应用,如 单标识到多标识转换中所述。

为避免这些情况,应用应避免创建包含帐户数据的文件,直到帐户注册成功完成。 如果应用在脱机时绝对必须创建文件,则在 SDK 联机后,它可以使用 MAMFileProtectionManager.protect 来更正文件的关联标识。

数据缓冲区保护

警告

不建议在单个文件中写入属于多个帐户的数据。 如果可能,请按标识组织应用的文件。

SDK 的 MAMDataProtectionManager 提供用于以 或 InputStream 格式检查和更改特定数据缓冲区byte[]的标记标识的方法。

MAMDataProtectionManager.protect 允许应用将数据与标识相关联,如果标识当前是加密策略的目标,请加密数据。 此加密数据适合存储在文件中的磁盘。

MAMDataProtectionManager 还允许查询与标识关联的数据并取消加密。

使用 的应用 MAMDataProtectionManager 应实现通知接收 MANAGEMENT_REMOVED 方。 有关更多详细信息 ,请参阅从 SDK 注册通知

此通知完成后,如果) 保护缓冲区时启用了文件加密,则通过此类保护的缓冲区将不再可读 (。 应用可以在处理MANAGEMENT_REMOVED通知时通过对所有缓冲区调用MAMDataProtectionManager.unprotect来防止这些缓冲区变得不可读。 如果想要保留标识信息,还可以在此通知期间安全地调用 protect 。 保证在通知期间禁用加密,并且处理程序中的调用 protect 不会加密数据缓冲区。

内容提供程序

多标识应用还必须保护通过 ContentProvider共享的数据,以防止不当共享托管内容。

应用必须在返回内容之前调用静态 MAMContentProvider 方法 isProvideContentAllowed(provider, contentIdentity) 。 如果此函数返回 false,则 不得 将内容返回到调用方。

如果ContentProvider返回 ParcelFileDescriptor,则不需要调用 isProvideContentAllowed 。 通过内容提供程序返回的文件描述符将根据文件标识自动处理。

选择性擦除

默认情况下,Intune 应用 SDK 会自动处理选择性擦除,删除与托管标识关联的所有 文件 。 之后,SDK 将正常关闭应用,完成活动并终止应用进程。

SDK 提供可选功能,使应用可以补充 (建议) 或替代默认擦除行为。

SDK 的默认擦除处理程序不处理受 MAMDataProtectionManager保护的数据缓冲区。 如果你的应用使用了此功能 ,则必须补充 或替代默认擦除处理程序以删除该数据。

注意

补充和重写默认擦除行为需要处理特定的 SDK 通知。 有关实现通知处理程序的更多详细信息 ,请参阅从 SDK 注册 通知。

补充默认擦除行为

为了补充默认 SDK 擦除行为,你的应用可以注册 WIPE_USER_AUXILIARY_DATAMAMNotificationType

SDK 将在执行默认选择性擦除 之前 发送此通知。 在删除数据和终止应用之前,SDK 将等待应用的通知处理程序完成。 你的应用应同步清除数据,在完成所有清理之前不会返回。

应用应强烈考虑使用 WIPE_USER_AUXILIARY_DATA补充默认擦除行为,因为特定于应用的清理对于多标识应用很常见。

重写默认擦除行为

若要替代默认的 SDK 擦除行为,应用可以注册 WIPE_USER_DATAMAMNotificationType

警告

应用绝不能同时注册 WIPE_USER_DATAWIPE_USER_AUXILIARY_DATA

重写默认 SDK 擦除行为对应用具有相当大的风险。 你的应用将完全负责删除与托管标识关联的所有数据,包括已为该标识标记的所有文件和数据缓冲区。

  • 如果托管标识受加密保护,并且应用的自定义擦除处理程序未完全删除所有托管数据,则任何剩余的托管文件将保持加密状态。 此数据将变得不可访问,并且你的应用可能无法正常处理尝试读取加密数据。
  • 如果你的应用的擦除处理程序删除了未使用托管标识标记的文件,则可能会导致非托管用户的数据丢失。

如果应用的自定义擦除处理程序从文件中删除托管数据,但希望将其他数据保留在文件中 ,则必须通过MAMFileProtectionManager.protect) 更改为非托管标识或空字符串来 (文件标识。

重写的擦除处理程序应同步清除数据,在完成所有清理之前不会返回。

请考虑在完成自定义擦除处理程序步骤后手动关闭应用,以防止用户在擦除发生后访问内存中数据。

退出条件

计划将大量时间用于验证应用的多标识集成。 开始测试之前:

  • 创建应用保护策略并将其分配给帐户。 这是测试托管帐户。
  • 创建另一个帐户,但不向其分配应用保护策略。 这是测试的非托管帐户。 或者,如果你的应用支持Microsoft Entra帐户以外的多种帐户类型,则可以使用现有的非 AAD 帐户作为非托管测试帐户。
  • 重新熟悉应用内策略的强制实施方式。 多标识测试要求你轻松区分应用在强制实施策略的情况下运行和未运行。 用于阻止屏幕截图的应用保护策略设置在快速测试策略强制实施时有效。
  • 请考虑应用提供的整个 UI 集。 枚举显示帐户数据的屏幕。 你的应用是否只一次显示单个帐户的数据,或者它可以同时显示属于多个帐户的数据?
  • 请考虑应用创建的整个文件集。 枚举其中哪些文件包含属于帐户的数据,而不是系统级数据。
    • 确定对其中每个文件验证加密的方式。
  • 请考虑应用可以与其他应用交互的整套方式。 枚举所有入口点和出口点。 应用可以引入哪些类型的数据? 它广播的意图是什么? 它实现哪些内容提供商?
    • 确定将如何练习其中每个数据共享功能。
    • 准备一个测试设备,该设备同时具有可以与应用交互的托管和非托管应用。
  • 考虑应用如何使最终用户能够与所有登录帐户交互。 用户是否需要在显示该帐户的数据之前手动切换到该帐户?

全面评估应用当前行为后,通过执行以下测试集来验证多标识集成。 请注意,这不是一个全面的列表,并且不保证应用的多标识实现是无 bug 的。

验证登录和注销方案

多标识应用最多支持 1 个托管帐户和多个非托管帐户。 这些测试有助于确保多标识集成不会在用户登录或注销时不正确地更改保护。

对于这些测试,请安装应用和Intune 公司门户;在开始测试之前不要登录。

应用场景 步骤
首先登录托管 - 首先使用托管帐户登录,并验证帐户的数据是否托管。
- 使用非托管帐户登录,并验证该帐户的数据不受管理。
首先登录非托管 - 首先使用非托管帐户登录,并验证该帐户的数据不受管理。
- 使用托管帐户登录并验证帐户的数据是否托管。
登录多个托管 - 首先使用托管帐户登录,并验证帐户的数据是否托管。
- 使用第二个托管帐户登录,并验证是否阻止用户登录,而无需先删除原始托管帐户。
注销托管 - 使用托管的非托管帐户登录到应用。
- 注销托管帐户。
- 确认已从应用中删除托管帐户,并且已删除该帐户的所有数据。
- 确认非托管帐户仍处于登录状态,未删除任何非托管帐户的数据,并且策略仍未应用。
注销非托管 - 使用托管的非托管帐户登录到应用。
- 注销非托管帐户。
- 确认已从应用中删除非托管帐户,并且已删除该帐户的所有数据。
- 确认托管帐户仍处于登录状态,未删除任何非托管帐户的数据,并且策略仍在应用。

验证活动标识和应用生命周期

多标识应用可能会显示具有单个帐户数据的视图,并允许用户显式更改当前正在使用的帐户。 它还可能同时显示包含多个帐户数据的视图。 这些测试有助于确保多标识集成在整个应用生命周期内为每个页面上的活动标识提供适当的保护。

对于这些测试,请安装应用和Intune 公司门户;在开始测试之前,使用托管和非托管帐户登录。

应用场景 步骤
单帐户视图,托管 - 切换到托管帐户。
- 导航到应用中显示单个帐户数据的所有页面。
- 确认策略已应用于每个页面。
单帐户视图,非托管 - 切换到非托管帐户。
- 导航到应用中显示单个帐户数据的所有页面。
- 确认策略未应用于任何页面。
多帐户视图 - 导航到应用中同时显示多个帐户数据的所有页面。
- 确认策略已应用于每个页面。
托管暂停 - 在显示托管数据并激活策略的屏幕上,导航到设备主屏幕或其他应用来暂停应用。
- 恢复应用。
- 确认仍应用策略。
非托管暂停 - 在显示非托管数据且未激活策略的屏幕上,导航到设备主屏幕或其他应用来暂停应用。
- 恢复应用。
- 确认策略未应用。
托管终止 - 在显示托管数据并激活策略的屏幕上,强制终止应用。
- 重启应用。
- 确认如果应用在屏幕上恢复,且托管帐户的数据 (预期) ,仍会应用策略。 如果应用在具有非托管帐户数据的屏幕上恢复,请确认该策略未应用。
非托管终止 - 在显示非托管数据并激活策略的屏幕上,强制终止应用。
- 重启应用。
- 确认如果应用在具有非托管帐户数据 (预期) 的屏幕上恢复,则不会应用策略。 如果应用在包含托管帐户数据的屏幕上恢复,请确认仍应用策略。
即席标识切换 - 尝试在帐户之间切换以及暂停/恢复/终止/重启应用。
- 确认托管帐户的数据始终受到保护,非托管帐户的数据永远不会受到保护。

验证数据共享方案

多标识应用可能会向其他应用发送数据以及从其他应用接收数据。 Intune 的应用保护策略具有指示此行为的设置。 这些测试有助于确保多标识集成遵循这些数据共享设置。

对于这些测试,请安装应用和Intune 公司门户;在开始测试之前,使用托管和非托管帐户登录。 此外:

  • 将托管帐户的策略设置为:
    • “将组织数据发送到其他应用”到“策略托管应用”。
    • “从其他应用接收数据”到“策略托管应用”。
  • 在测试设备上安装其他应用:
    • 一个托管应用,其目标策略与应用相同,可以发送和接收数据 (,如 Microsoft Outlook) 。
    • 可以发送和接收数据的任何非托管应用。
  • 使用托管测试帐户登录到其他托管应用。 即使其他托管应用是多标识,也只能使用托管帐户登录。

如果你的应用能够将数据发送到其他应用,例如 Microsoft Outlook 向 Microsoft Office 发送文档附件:

应用场景 步骤
将托管标识发送到非托管应用 - 切换到托管帐户。
- 导航到应用可以发送数据的位置。
- 尝试将数据发送到非托管应用。
- 应阻止你将数据发送到非托管应用。
将托管标识发送到托管应用 - 切换到托管帐户。
- 导航到应用可以发送数据的位置。
- 尝试将数据发送到已登录托管帐户的其他托管应用。
- 应允许将数据发送到托管应用。
将非托管标识发送到托管应用 - 切换到非托管帐户。
- 导航到应用可以发送数据的位置。
- 尝试将数据发送到已登录托管帐户的其他托管应用。
- 应阻止你将数据发送到其他托管应用。
将非托管标识发送到非托管应用 - 切换到非托管帐户。
- 导航到应用可以发送数据的位置。
- 尝试将数据发送到非托管应用。
- 应始终允许将非托管帐户的数据发送到非托管应用。

你的应用可能会主动从其他应用导入数据,例如从 Microsoft OneDrive 附加文件的 Microsoft Outlook。 你的应用也可能被动接收来自其他应用的数据,例如 Microsoft Office 从 Microsoft Outlook 附件打开文档。 接收应用保护策略设置涵盖这两种方案。

如果你的应用能够主动从其他应用导入数据:

应用场景 步骤
从非托管应用导入托管标识 - 切换到托管帐户。
- 导航到应用可以从其他应用导入数据的位置。
- 尝试从非托管应用导入数据。
- 应阻止你从非托管应用导入数据。
从托管应用导入托管标识 - 切换到托管帐户。
- 导航到应用可以从其他应用导入数据的位置。
- 尝试从已登录托管帐户的其他托管应用导入数据。
- 应允许从其他托管应用导入数据。
从托管应用导入非托管标识 - 切换到非托管帐户。
- 导航到应用可以从其他应用导入数据的位置。
- 尝试从已登录托管帐户的其他托管应用导入数据。
- 应阻止你从其他托管应用导入数据。
从非托管应用导入非托管标识 - 切换到非托管帐户。
- 导航到应用可以从其他应用导入数据的位置。
- 尝试从非托管应用导入数据。
- 应始终允许从非托管帐户的非托管应用导入数据。

如果你的应用能够被动接收来自其他应用的数据:

应用场景 步骤
从非托管应用接收托管标识 - 切换到托管帐户。
- 切换到非托管应用。
- 导航到可以发送数据的位置。
- 尝试将数据从非托管应用发送到你的应用。
- 应用的托管帐户无法从非托管应用接收数据。
从托管应用接收托管标识 - 切换到托管帐户。
- 切换到已登录托管帐户的其他托管应用。
- 导航到可以发送数据的位置。
- 尝试将数据从托管应用发送到应用。
- 应允许应用的托管帐户从其他托管应用接收数据。
从托管应用接收非托管标识 - 切换到非托管帐户。
- 切换到已登录托管帐户的其他托管应用。
- 导航到可以发送数据的位置。
- 尝试将数据从托管应用发送到应用。
- 你的应用的非托管帐户无法从托管应用接收数据。
从非托管应用接收非托管标识 - 切换到非托管帐户。
- 切换到非托管应用。
- 导航到可以发送数据的位置。
- 尝试将数据从非托管应用发送到你的应用。
- 应始终允许应用的非托管帐户从非托管应用接收数据。

这些测试中的失败可能表示应用在尝试发送或接收数据时没有设置正确的活动标识。 可以通过在发送/接收时利用 SDK 的 get 标识 API 来调查此问题,以确认活动标识是否已正确设置。

验证选择性擦除方案

多标识应用可能已补充或重写 SDK 的默认擦除行为。 这些测试有助于确保在启动擦除时,多标识集成正确删除托管数据,而不会影响非托管数据。

警告

提醒:如果你的应用利用 了 MAMDataProtectionManager.protect,它必须为WIPE_USER_DATA实现处理程序WIPE_USER_AUXILIARY_DATA

对于这些测试,请安装应用和Intune 公司门户;在开始测试之前,使用托管和非托管帐户登录。 对于这两个帐户,请练习用于存储帐户数据的应用方案。

应用场景 前提 条件 步骤
补充擦除处理程序 你的应用已为 WIPE_USER_AUXILIARY_DATA - 从Microsoft Intune管理中心发出选择性擦除
- 通常通过日志记录) 确认 (擦除处理程序已成功执行。
- 确认已从应用中删除托管帐户,并且已删除该帐户的所有数据。
- 确认非托管帐户仍处于登录状态,未删除任何非托管帐户的数据,并且策略仍未应用。
重写的擦除处理程序 你的应用已为 WIPE_USER_DATA - 从Microsoft Intune管理中心发出选择性擦除
- 通常通过日志记录) 确认 (擦除处理程序已成功执行。
- 确认已从应用中删除托管帐户,并且已删除该帐户的所有数据。
- 确认非托管帐户仍处于登录状态,未删除任何非托管帐户的数据,并且策略仍未应用。
- 确认应用在擦除处理程序完成后已正常退出或仍处于正常状态。
手动文件保护 - 应用调用 MAMFileProtectionManager.protect
- 应用已实现处理程序 WIPE_USER_DATA
- 确保已练习应用手动保护至少一个属于托管帐户的文件的方案。
- 从Microsoft Intune管理中心发出选择性擦除
- 确认文件已删除。
手动数据缓冲区保护 - 应用调用 MAMDataProtectionManager.protect
- 你的应用已为 WIPE_USER_AUXILIARY_DATA 或 实现了处理程序 WIPE_USER_DATA
- 确保已练习应用手动保护至少一个属于托管帐户的数据缓冲区的方案。
- 从Microsoft Intune管理中心发出选择性擦除
- 确认数据缓冲区已从存储到的任何文件中删除,并且你的应用仍可以从这些文件读取非托管数据。

后续步骤

完成上述所有 退出条件 后,你的应用现在已成功集成为多标识,并且可以基于每个标识强制实施应用保护策略。 后续部分(阶段 6:应用程序配置阶段 7:应用参与功能)可能是必需的,也可能不需要,具体取决于应用所需的应用保护策略支持。 如果不确定这些部分是否适用于你的应用,请重新访问 SDK 集成的关键决策