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

前线工作人员,如零售同事、机组人员和现场服务人员,通常使用共享移动设备来执行其工作。 如果用户共享其密码或 PIN(有意或无意)访问共享设备上的客户和业务数据,这些共享设备可能会面临安全风险。

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

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

  1. 设备管理员手动将设备设置为可供共享,或者使用移动设备管理 (MDM) 提供商(例如 Microsoft Intune)来进行设置。 首选方案是使用 MDM,因为它支持通过零接触预配以共享设备模式大规模配置设备。 MDM 将Microsoft Authenticator应用推送到设备,并通过对设备进行托管配置更新,为每个设备启用“共享模式”。 此共享模式设置更改设备上的受支持应用的行为。 MDM 提供程序提供的此配置为设备设置共享设备模式,并使用 Authenticator 应用触发共享设备注册。

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

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

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

    Important

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

在共享设备模式下设置设备

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

Microsoft Intune支持在Microsoft Entra共享设备模式下为设备进行零接触预配,这意味着可以在 Intune 中设置和注册设备,同时与前线工作人员进行最少的交互。 若要在使用 Microsoft Intune 作为 MDM 时在共享设备模式下设置设备,请参阅在Microsoft Entra共享设备模式下为设备设置注册

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

你的用户取决于你,以确保其数据不会泄露给其他用户。 以下部分提供了有用的信号,用于向应用程序指示发生了更改并应进行处理。 你负责检查每次使用应用时设备上的用户状态,然后清除以前的用户数据。 这也包括它在多任务处理时从后台重新加载的情况。 在用户更改时,应确保清除前一个用户的数据,并删除应用程序中显示的任何缓存数据。 强烈建议你和你的公司在更新应用以支持共享设备模式后执行安全审查过程。

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

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

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)。 例如,应用程序可能具有“注册”功能,这不适合一线工作人员,因为它们可能已有帐户。 如果应用程序处于共享设备模式,你可能还需要为应用程序的数据处理添加额外的安全性。

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

以下代码片段演示了使用 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 在处于共享模式的设备上运行的应用中注销用户时,将从应用和设备中删除已登录帐户和缓存的令牌。

下图显示了应用运行时可能发生的整体应用生命周期和常见事件。 此图展示了从 Activity 启动,到账户登录和退出的时序,以及暂停、恢复和停止 Activity 等事件如何穿插其中。

共享设备应用生命周期

后续步骤

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

Android 设备的共享设备模式