适用于 Android 设备的共享设备模式

一线工作者(例如零售职员、机组人员和现场服务工人)通常使用共享移动设备来完成其工作。 如果用户共享其密码或 PIN(不管是有意还是无意)来访问共享设备上的客户和数据业务数据,那么这些共享设备可能会有安全风险。

共享设备模式能够将 Android 8.0 或更高版本的设备配置为可由员工更安全地共享。 员工可以登录一次,并对所有支持单点登录 (SSO) 的应用程序使用 SSO,从而更快地访问信息。 当员工完成班次或任务后注销时,他们会自动注销设备和所有受支持的应用程序,使设备可供下一个用户使用。

要利用共享设备模式功能,需要应用开发人员和云设备管理员配合工作:

  1. 设备管理员将手动或使用 Microsoft Intune 等移动设备管理 (MDM) 提供程序来准备好要共享的设备。 首选选项是使用 MDM,因为它允许通过零接触预配大规模在共享设备模式下设置设备。 MDM 将 Microsoft Authenticator 应用推送到设备,并通过设备的配置文件更新来为每台设备启用“共享模式”。 正是此“共享模式”设置更改了设备上受支持应用的行为。 MDM 提供程序提供的此配置为设备设置共享设备模式,并使用 Authenticator 应用触发共享设备注册。

  2. 应用程序开发人员编写单帐户应用程序(共享设备模式不支持多帐户应用程序)来处理以下场景:

    • 通过任何受支持的应用程序在整个设备上将用户登录
    • 通过任何受支持的应用程序在整个设备上将用户注销
    • 查询设备的状态,以确定应用程序是否位于处于共享设备模式的设备上
    • 查询用户的设备状态,以确定自上次使用应用程序以来是否发生了任何更改

    支持共享设备模式应被视为应用程序的一项功能升级,并且会有助于在多个用户使用同一设备的环境中提升该应用程序的采用率。

    重要

    在 Android 上支持共享设备模式的 Microsoft 应用程序不需要进行任何更改,只需在设备上安装即可获得共享设备模式带来的好处。

为设备设置共享设备模式

若要将 Android 设备配置为支持共享设备模式,它应运行 Android OS 8.0 或更高版本。 还应通过恢复出厂设置或者卸载并重新安装所有 Microsoft 和其他启用共享设备模式的应用来擦除设备。

Microsoft Intune 支持对 Microsoft Entra 共享设备模式下的设备进行零接触预配,这意味着可以直接在 Intune 中设置和注册设备,几乎不需要与一线工作人员互动。 若要在将 Microsoft Intune 用作 MDM 时为设备设置共享设备模式,请参阅在 Microsoft Entra 共享设备模式下为设备设置注册

修改 Android 应用程序以支持共享设备模式

用户依赖于你来确保其数据不会泄露给其他用户。 以下部分提供了有用的信号,用于向应用程序指示已发生了需要处理的更改。 每次使用应用时,你都要负责检查设备上用户的状态,并清除上一个用户的数据。 这还包括检查应用是不是从正在执行多个任务的后台重新加载的。 发生用户更改后,你应确保前一个用户的数据已清除,并且应用程序中显示的所有缓存数据已删除。 我们强烈建议你和你的公司在更新应用以支持共享设备模式之后,执行安全评审过程。

将 Microsoft 身份验证库 (MSAL) SDK 添加到应用程序的依赖项

请在 build.gradle 文件中将 MSAL 库添加为依赖项,如下所示:

dependencies{
  implementation 'com.microsoft.identity.client.msal:5.+'
}

将应用配置为使用共享设备模式

使用 Microsoft 身份验证库 (MSAL) SDK 编写的应用程序可以管理单帐户或多帐户。 有关详细信息,请参阅单帐户模式或多帐户模式。 共享设备模式应用只能在单帐户模式下工作。

如果不打算支持多帐户模式,请在 msal 配置文件中将 "account_mode" 设置为 "SINGLE"。 这可以确保你的应用始终获得 ISingleAccountPublicClientApplication,并大大简化你的 MSAL 集成。 "account_mode" 的默认值为 "MULTIPLE",因此,如果使用 "single account" 模式,则必须在配置文件中更改此值。

下面是一个配置文件示例:

{
  "client_id": "Client ID after app registration at https://aka.ms/MobileAppReg",
  "authorization_user_agent": "WEBVIEW",
  "redirect_uri": "Redirect URI after app registration at https://aka.ms/MobileAppReg",
  "account_mode": "SINGLE",
  "broker_redirect_uri_registered": true,
  "authorities": [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

有关设置配置文件的详细信息,请参阅配置文档

同时支持单帐户和多帐户

可将应用构建为支持在个人设备和共享设备上运行。 如果应用目前支持多个帐户,而你想要支持共享设备模式,请添加对单帐户模式的支持。

你可能还希望应用根据其运行的设备类型来更改应用行为。 使用 ISingleAccountPublicClientApplication.isSharedDevice() 确定何时在单帐户模式下运行。

有两个不同的接口表示应用程序所在的设备类型。 从 MSAL 的应用程序工厂请求应用程序实例时,会自动提供正确的应用程序对象。

以下对象模型演示了可以接收的对象类型,以及该对象在共享设备上下文中的含义:

公共客户端应用程序继承模型

在获取 PublicClientApplication 对象时,需要执行类型检查并强制转换为相应的接口。 以下代码可检查多帐户模式或单帐户模式,并相应地强制转换应用程序对象:

private IPublicClientApplication mApplication;

        // Running in personal-device mode?
        if (mApplication instanceOf IMultipleAccountPublicClientApplication) {
          IMultipleAccountPublicClientApplication multipleAccountApplication = (IMultipleAccountPublicClientApplication) mApplication;
          ...
        // Running in shared-device mode?
        } else if (mApplication instanceOf ISingleAccountPublicClientApplication) {
           ISingleAccountPublicClientApplication singleAccountApplication = (ISingleAccountPublicClientApplication) mApplication;
            ...
        }

根据应用是在共享设备还是个人设备上运行而存在以下差异:

共享模式设备 个人设备
帐户 单帐户 多帐户
登录 全局 全局
注销 全局 每个应用程序都可以控制退出登录是否在应用的本地进行。
支持的帐户类型 仅限工作帐户 支持个人和工作帐户

初始化 PublicClientApplication 对象

如果在 MSAL 配置文件中设置了 "account_mode":"SINGLE",则可以放心地将返回的应用程序对象转换为 ISingleAccountPublicCLientApplication

private ISingleAccountPublicClientApplication mSingleAccountApp;

PublicClientApplication.create(
    this.getApplicationCOntext(),
    R.raw.auth_config_single_account,
    new PublicClientApplication.ApplicationCreatedListener() {

        @Override
        public void onCreated(IPublicClientApplication application){
            mSingleAccountApp = (ISingleAccountPublicClientApplication)application;
        }

        @Override
        public void onError(MsalException exception){
            /*Fail to initialize PublicClientApplication */
        }
    });

检测共享设备模式

检测共享设备模式对于应用程序而言非常重要。 许多应用程序在共享设备上使用时,都需要改变用户体验 (UX)。 例如,应用程序可能会提供一个“注册”功能,而该功能并不适用于一线工作者,因为他们可能已有一个帐户。 如果应用程序处于共享设备模式,你还可能想要为应用程序的数据处理添加额外的安全性。

使用 IPublicClientApplication 中的 isSharedDevice API 确定应用是否正在处于共享设备模式的设备上运行。

以下代码片段演示使用 isSharedDevice API 的示例。

deviceModeTextView.setText(mSingleAccountApp.isSharedDevice() ? "Shared" : "Non-Shared");

获取已登录用户并确定该设备上的用户是否已更改

支持共享设备模式的另一个重要部分是确定设备上用户的状态,并在设备上的用户已更改或者设备上根本没有任何用户时清除应用程序数据。 你需要负责确保数据不会泄露给其他用户。

可以使用 getCurrentAccountAsync API 查询设备上当前已登录的帐户。

loadAccount 方法检索已登录用户的帐户。 onAccountChanged 方法确定已登录用户是否已更改,如果已更改,则清除:

private void loadAccount()
{
  mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback())
  {
    @Override
    public void onAccountLoaded(@Nullable IAccount activeAccount)
    {
      if (activeAccount != null)
      {
        signedInUser = activeAccount;
        final AcquireTokenSilentParameters silentParameters = new AcquireTokenSilentParameters.Builder()
                        .fromAuthority(signedInUser.getAuthority())
                        .forAccount(signedInUser)
                        .withScopes(Arrays.asList(getScopes()))
                        .withCallback(getAuthSilentCallback())
                        .build();
        mSingleAccountApp.acquireTokenSilentAsync(silentParameters);
      }
    }
    @Override
    public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable Iaccount currentAccount)
    {
      if (currentAccount == null)
      {
        //Perform a cleanup task as the signed-in account changed.
        cleaUp();
      }
    }
    @Override
    public void onError(@NonNull Exception exception)
    {
        //getCurrentAccountAsync failed
    }
  }
}

将用户全局登录

将设备配置为共享设备后,应用程序可以调用 signIn API 将帐户登录。 第一个应用将帐户登录后,该帐户将全局性地可供设备上所有符合条件的应用使用。

final SignInParameters signInParameters = ... /* create SignInParameters object */
mSingleAccountApp.signIn(signInParameters);

将用户全局注销

以下代码将删除已登录的帐户,并且不仅从应用中清除缓存的令牌,而且还从处于共享设备模式下的设备中清除缓存的令牌。 不过,它不会清除应用程序中的数据。 你必须清除应用程序中的数据,并清除应用程序可能会向用户显示的所有缓存数据。

mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
    @Override
    public void onSignOut() {
        // clear data from your application
    }

    @Override
    public void onError(@NonNull MsalException exception) {
        // signout failed, show error
    }
});

接收广播以检测从其他应用程序启动的全局注销

若要接收帐户更改广播,需要注册广播接收器。 建议通过上下文注册的接收器注册广播接收器。

接收到帐户更改广播后,立即获取已登录用户,并确定设备上的用户是否已更改。 如果检测到更改,则为以前登录的帐户启动数据清理。 建议适当停止任何操作,并进行数据清理。

以下代码片段演示如何注册广播接收器。

private static final String CURRENT_ACCOUNT_CHANGED_BROADCAST_IDENTIFIER = "com.microsoft.identity.client.sharedmode.CURRENT_ACCOUNT_CHANGED";
private BroadcastReceiver mAccountChangedBroadcastReceiver;
private void registerAccountChangeBroadcastReceiver(){
    mAccountChangedBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //INVOKE YOUR PRIOR ACCOUNT CLEAN UP LOGIC HERE
        }
    };
    IntentFilter filter = new

    IntentFilter(CURRENT_ACCOUNT_CHANGED_BROADCAST_IDENTIFIER);
    this.registerReceiver(mAccountChangedBroadcastReceiver, filter);
}

支持共享设备模式的 Microsoft 应用程序

以下 Microsoft 应用程序支持 Microsoft Entra 共享设备模式:

支持共享设备模式的第三方 MDM

这些第三方移动设备管理 (MDM) 提供程序支持 Microsoft Entra 共享设备模式:

共享设备退出登录和整体应用生命周期

当用户退出登录时,你需要采取措施来保护用户的隐私和数据。 例如,如果要生成医疗记录应用,你会想要确保在用户退出登录时清除以前显示的患者记录。 你的应用程序必须准备好数据隐私保护机制,并在应用程序每次进入前台时进行检查。

当应用使用 MSAL 来注销处于共享模式的设备上运行的应用中的用户时,将从该应用和设备中删除已登录的帐户和缓存的令牌。

下图显示了整体应用生命周期,以及应用运行时可能发生的常见事件。 该图从活动启动时间开始,涵盖了登录和退出登录帐户,以及事件(例如暂停、恢复和停止活动)的适应方式。

共享设备应用生命周期

后续步骤

设置 Android 设备以在共享设备模式下运行应用并测试应用。

适用于 Android 设备的共享设备模式