单帐户和多帐户公共客户端应用Single and multiple account public client apps

本文帮助你了解单帐户和多帐户公共客户端应用中使用的类型,并重点介绍单帐户公共客户端应用。This article will help you understand the types used in single and multiple account public client apps, with a focus on single account public client apps.

Azure Active Directory 身份验证库 (ADAL) 为服务器建模。The Azure Active Directory Authentication Library (ADAL) models the server. 而 Microsoft 身份验证库 (MSAL) 则为客户端应用程序建模。The Microsoft Authentication Library (MSAL) instead models your client application. 大多数 Android 应用都被视为公共客户端。The majority of Android apps are considered public clients. 公共客户端是无法安全保存机密的应用。A public client is an app that can't securely keep a secret.

MSAL 提供专业的 PublicClientApplication API 交互面来简化和阐明每次只能使用一个帐户的应用的开发体验。MSAL specializes the API surface of PublicClientApplication to simplify and clarify the development experience for apps that allow only one account to be used at a time. PublicClientApplication 包括 SingleAccountPublicClientApplicationMultipleAccountPublicClientApplication 子类。PublicClientApplication is subclassed by SingleAccountPublicClientApplication and MultipleAccountPublicClientApplication. 下图显示了这些类之间的关系。The following diagram shows the relationship between these classes.

SingleAccountPublicClientApplication UML 类关系图

单帐户公共客户端应用程序Single account public client application

使用 SingleAccountPublicClientApplication 类可以创建每次只允许登录一个帐户的基于 MSAL 的应用。The SingleAccountPublicClientApplication class allows you to create an MSAL-based app that only allows a single account to be signed in at a time. SingleAccountPublicClientApplicationPublicClientApplication 的差别体现在以下方面:SingleAccountPublicClientApplication differs from PublicClientApplication in the following ways:

  • MSAL 跟踪当前已登录的帐户。MSAL tracks the currently signed-in account.
    • 如果应用使用中介(在 Azure 门户中进行应用注册期间使用的默认设置),并且安装在具有中介的设备上,则 MSAL 将验证该帐户是否仍在该设备上可用。If your app is using a broker (the default during Azure portal app registration) and is installed on a device where a broker is present, MSAL will verify that the account is still available on the device.
  • signIn 允许通过请求范围单独显式登录帐户。signIn allows you to sign in an account explicitly and separately from requesting scopes.
  • acquireTokenSilent 不需要帐户参数。acquireTokenSilent doesn't require an account parameter. 如果确实提供了一个帐户,但该帐户与 MSAL 跟踪的当前帐户不匹配,则会引发 MsalClientExceptionIf you do provide an account, and the account you provide doesn't match the current account tracked by MSAL, an MsalClientException is thrown.
  • acquireToken 不允许用户切换帐户。acquireToken doesn't allow the user to switch accounts. 如果用户尝试切换到其他帐户,则会引发异常。If the user attempts to switch to a different account, an exception is thrown.
  • getCurrentAccount 返回提供以下内容的结果对象:getCurrentAccount returns a result object that provides the following:
    • 一个指示帐户是否已更改的布尔值。A boolean indicating whether the account changed. 例如,从设备中删除某个帐户后,该帐户可能就会更改。An account may be changed as a result of being removed from the device, for example.
    • 以前的帐户。The prior account. 从设备中删除了帐户或者登录了新帐户时,如果需要执行任何本地数据清理,这些信息将很有用。This is useful if you need to do any local data cleanup when the account is removed from the device or when a new account is signed in.
    • currentAccount。The currentAccount.
  • signOut 从设备中删除与客户端关联的所有令牌。signOut removes any tokens associated with your client from the device.

如果在设备上安装了 Android 身份验证中介(例如 Microsoft Authenticator 或 Intune 公司门户),并且应用已配置为使用该中介,则 signOut 不会从设备中删除帐户。When an Android Authentication broker such as Microsoft Authenticator or Intune Company Portal is installed on the device and your app is configured to use the broker, signOut won't remove the account from the device.

单帐户方案Single account scenario

以下伪代码演示 SingleAccountPublicClientApplication 的用法。The following pseudo code illustrates using SingleAccountPublicClientApplication.

// Construct Single Account Public Client Application
ISingleAccountPublicClientApplication app = PublicClientApplication.createSingleAccountPublicClientApplication(getApplicationContext(), R.raw.msal_config);

String[] scopes = {"https://microsoftgraph.chinacloudapi.cn/user.read"};
IAccount mAccount = null;

// Acquire a token interactively
// The user will get a UI prompt before getting the token.
app.signIn(getActivity(), scopes, new AuthenticationCallback()
{

        @Override
        public void onSuccess(IAuthenticationResult authenticationResult) 
        {
            mAccount = authenticationResult.getAccount();
        }

        @Override
        public void onError(MsalException exception)
        {
        }

        @Override
        public void onCancel()
        {
        }
    }
);

// Load Account Specific Data
getDataForAccount(account);

// Get Current Account
ICurrentAccountResult currentAccountResult = app.getCurrentAccount();
if (currentAccountResult.didAccountChange())
{
    // Account Changed Clear existing account data
    clearDataForAccount(currentAccountResult.getPriorAccount());
    mAccount = currentAccountResult.getCurrentAccount();
    if (account != null)
    {
        //load data for new account
        getDataForAccount(account);
    }
}

// Sign out
if (app.signOut())
{
    clearDataForAccount(mAccount);
    mAccount = null;
}

多帐户公共客户端应用程序Multiple account public client application

MultipleAccountPublicClientApplication 类用于创建允许同时登录多个帐户的基于 MSAL 的应用。The MultipleAccountPublicClientApplication class is used to create MSAL-based apps that allow multiple accounts to be signed in at the same time. 使用该类可以获取、添加和删除帐户,如下所述:It allows you to get, add, and remove accounts as follows:

添加帐户Add an account

通过调用 acquireToken 一次或多次,在应用程序中使用一个或多个帐户。Use one or more accounts in your application by calling acquireToken one or more times.

获取帐户Get accounts

  • 调用 getAccount 可获取特定的帐户。Call getAccount to get a specific account.
  • 调用 getAccounts 可获取应用当前已知的帐户列表。Call getAccountsto get a list of accounts currently known to the app.

应用无法枚举中介应用已知的设备上的所有 Microsoft 标识平台帐户。Your app won't be able to enumerate all Microsoft identity platform accounts on the device known to the broker app. 它只能枚举应用使用的帐户。It can only enumerate accounts that have been used by your app. 这些函数不会返回已从设备中删除的帐户。Accounts that have been removed from the device won't be returned by these functions.

删除帐户Remove an account

可以结合帐户标识符调用 removeAccount 来删除帐户。Remove an account by calling removeAccount with an account identifier.

如果应用配置为使用中介,并且设备上已安装了中介,则调用 removeAccount 时,不会从中介中删除帐户。If your app is configured to use a broker, and a broker is installed on the device, the account won't be removed from the broker when you call removeAccount. 只会删除与客户端关联的令牌。Only tokens associated with your client are removed.

多帐户方案Multiple account scenario

以下伪代码演示如何创建多帐户应用、列出设备上的帐户和获取令牌。The following pseudo code shows how to create a multiple account app, list accounts on the device, and acquire tokens.

// Construct Multiple Account Public Client Application
IMultipleAccountPublicClientApplication app = PublicClientApplication.createMultipleAccountPublicClientApplication(getApplicationContext(), R.raw.msal_config);

String[] scopes = {"https://microsoftgraph.chinacloudapi.cn/user.read"};
IAccount mAccount = null;

// Acquire a token interactively
// The user will be required to interact with a UI to obtain a token
app.acquireToken(getActivity(), scopes, new AuthenticationCallback()
 {

        @Override
        public void onSuccess(IAuthenticationResult authenticationResult) 
        {
            mAccount = authenticationResult.getAccount();
        }

        @Override
        public void onError(MsalException exception)
        {
        }

        @Override
        public void onCancel()
        {
        }
 });

...

// Get the default authority
String authority = app.getConfiguration().getDefaultAuthority().getAuthorityURL().toString();

// Get a list of accounts on the device
List<IAccount> accounts = app.getAccounts();

// Pick an account to obtain a token from without prompting the user to sign in
IAccount selectedAccount = accounts.get(0);

// Get a token without prompting the user
app.acquireTokenSilentAsync(scopes, selectedAccount, authority, new SilentAuthenticationCallback()
{

        @Override
        public void onSuccess(IAuthenticationResult authenticationResult) 
        {
            mAccount = authenticationResult.getAccount();
        }

        @Override
        public void onError(MsalException exception)
        {
        }
});