单帐户和多个帐户公共客户端应用

本文将帮助你了解单帐户和多个帐户公共客户端应用中使用的类型,重点介绍单帐户公共客户端应用。

Azure Active Directory身份验证库(ADAL)为服务器建模。 Microsoft 身份验证库(MSAL)则以客户端应用程序为模型。 大多数 Android 应用被视为公共客户端。 公共客户端是无法安全地保留机密的应用。

MSAL 针对一次仅允许使用一个帐户的应用,对 PublicClientApplication 的 API 进行了专门化设计,以简化并明晰开发体验。 PublicClientApplicationSingleAccountPublicClientApplicationMultipleAccountPublicClientApplication 子类化。 下图显示了这些类之间的关系。

SingleAccountPublicClientApplication UML 类图

单帐户公共客户端应用程序

SingleAccountPublicClientApplication 允许你创建一个基于 MSAL 的应用,该应用一次只允许一个帐户登录。 SingleAccountPublicClientApplicationPublicClientApplication的不同之处如下:

  • MSAL 会记录当前已登录的账户。
    • 如果你的应用正在使用中转站(Microsoft Entra应用注册期间的默认应用),并且安装在存在中转站的设备上,MSAL 将验证该帐户是否仍可在设备上使用。
  • signIn 允许你显式且独立于请求范围登录帐户。
  • acquireTokenSilent 不需要帐户参数。 如果确实提供了一个帐户,但该帐户与 MSAL 跟踪的当前帐户不匹配,则会引发 MsalClientException
  • acquireToken 不允许用户切换帐户。 如果用户尝试切换到其他帐户,则会引发异常。
  • getCurrentAccount 返回提供以下内容的结果对象:
    • 一个布尔值,指示帐户是否已更改。 例如,帐户可能会因为已从设备中移除而发生变化。
    • 先前的账户。 如果需要在从设备中删除帐户或登录新帐户时执行任何本地数据清理,这非常有用。
    • currentAccount。
  • signOut 会从设备中移除与您的客户端关联的所有令牌。

当设备上安装了 Android 身份验证代理(如 Microsoft Authenticator、链接到 Windows(LTW)或 Intune 公司门户,并且应用配置为使用中转站时,signOut不会从设备中删除该帐户。

单帐户方案

以下伪代码演示了如何使用 SingleAccountPublicClientApplication

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

String[] scopes = {"User.Read"};
IAccount mAccount = null;

// Acquire a token interactively
// The user will get a UI prompt before getting the token.
SignInParameters signInParameters = SignInParameters.builder()
        .withActivity(getActivity()) // Pass the current activity
        .withScopes(scopes) // Specify the scopes
        .withCallback(new AuthenticationCallback() {
            @Override
            public void onSuccess(IAuthenticationResult authenticationResult){
                mAccount = authenticationResult.getAccount();
            }
    
            @Override
            public void onError(MsalException exception){
            }
    
            @Override
            public void onCancel(){
            }
        })
        .build();


app.signIn(signInParameters);

// 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;
}

多账户公共客户端应用程序

MultipleAccountPublicClientApplication 类用于创建基于 MSAL 的应用,这些应用允许同时登录多个帐户。 它允许获取、添加和删除帐户,如下所示:

添加帐户

通过调用 acquireToken 一次或多次,在应用程序中使用一个或多个帐户。

获取帐户

  • 调用 getAccount 以获取特定帐户。
  • 调用 getAccounts以获取应用当前已知的帐户列表。

你的应用将无法列举出设备上代理应用已知的所有 Microsoft 标识平台账户。 它只能列举你的应用已使用过的账户。 这些函数不会返回从设备中删除的帐户。

删除帐户

使用帐户标识符调用 removeAccount 来删除帐户。

如果你的应用配置为使用中转站,并且已在设备上安装中转站,则在调用 removeAccount时不会从中转站中删除该帐户。 仅会删除与您的客户端关联的令牌。

多账户场景

以下伪代码演示如何创建多个帐户应用、列出设备上的帐户以及获取令牌。

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

String[] scopes = {"User.Read"};
IAccount mAccount = null;

// Acquire a token interactively
// The user will be required to interact with a UI to obtain a token
AcquireTokenParameters acquireTokenParameters = new AcquireTokenParameters.Builder()
        .startAuthorizationFromActivity(getActivity())
        .withScopes(scopes)
        .withCallback(new AuthenticationCallback(){
    
            @Override
            public void onSuccess(IAuthenticationResult authenticationResult) {
                mAccount = authenticationResult.getAccount();
            }
    
            @Override
            public void onError(MsalException exception){
            }
    
            @Override
            public void onCancel(){
            }
         })
        .build();
app.acquireToken(acquireTokenParameters);


...

// 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
AcquireTokenSilentParameters acquireTokenSilentParameters = new AcquireTokenSilentParameters.Builder()
        .withScopes(scopes)
        .forAccount(selectedAccount)
        .fromAuthority(authority)
        .withCallback(new SilentAuthenticationCallback() {

            @Override
            public void onSuccess(IAuthenticationResult authenticationResult) {
                mAccount = authenticationResult.getAccount();
            }
    
            @Override
            public void onError(MsalException exception){
            }
        })
        .build();
app.acquireTokenSilentAsync(acquireTokenSilentParameters);