你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 MSAL.NET 从令牌缓存获取令牌

使用适用于 .NET 的 Microsoft 身份验证库 (MSAL.NET) 获取访问令牌时,将缓存该令牌。 当应用程序需要令牌时,它应首先尝试从缓存中提取令牌。

可以通过检查 AuthenticationResult.AuthenticationResultMetadata.TokenSource 属性来监视令牌的来源。

网站和 Web API

ASP.NET Core 和 ASP.NET 经典版网站应与 Microsoft.Identity.Web(用于 MSAL.NET 的包装器)集成。 可以按照令牌缓存序列化中所述配置内存令牌缓存或分布式令牌缓存。

基于 ASP.NET Core 的 Web API 应当使用 Microsoft.Identity.Web。 基于 ASP.NET 经典版的 Web API 通过调用 AcquireTokenOnBehalfOf 直接使用 MSAL,应当配置内存或分布式缓存。 有关详细信息,请参阅 MSAL.NET 中的令牌缓存序列化。 没有理由调用 AcquireTokenSilent API,因为没有用于清除缓存的 API。 可以通过为基础缓存存储(例如 MemoryCache、Redis,等等)设置逐出策略来管理缓存大小。

Web 服务 / 守护程序应用

通过调用 AcquireTokenForClient 为应用标识请求令牌(不涉及用户)的应用程序可以依赖于 MSAL 的内部缓存、定义其自己的内存令牌缓存或分布式令牌缓存。 有关说明和详细信息,请参阅 MSAL.NET 中的令牌缓存序列化

由于不涉及任何用户,因此没有理由调用 AcquireTokenSilentAcquireTokenForClient 会自行在缓存中查看,因为没有用于清除缓存的 API。 缓存大小与你需要令牌的租户和资源的数量成正比。 可以通过为基础缓存存储(例如 MemoryCache、Redis 等)设置逐出策略来管理缓存大小。

桌面、命令行和移动应用程序

桌面、命令行和移动应用程序应首先调用 AcquireTokenSilent 方法,以验证缓存中是否有可接受的令牌。 在许多情况下,可以基于缓存中的令牌获取具有更多范围的另一个令牌。 当令牌快到期时也可以刷新令牌(因为令牌缓存也包含一个刷新令牌)。

对于需要用户交互的身份验证流,MSAL 将缓存访问、刷新和 ID 令牌,以及 IAccount 对象,该对象代表有关某一个帐户的信息。 详细了解 IAccount。 对于客户端凭据之类的应用程序流,只缓存访问令牌,因为 IAccount 对象和 ID 令牌需要有用户,而刷新令牌不适用。

建议的模式是首先调用 AcquireTokenSilent 方法。 如果 AcquireTokenSilent 失败,则使用其他方法获取令牌。

在以下示例中,应用程序首先尝试从令牌缓存中获取令牌。 如果引发了 MsalUiRequiredException 异常,则应用程序将以交互方式获取令牌。

var accounts = await app.GetAccountsAsync();

AuthenticationResult result = null;
try
{
     result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                       .ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
    // A MsalUiRequiredException happened on AcquireTokenSilent.
    // This indicates you need to call AcquireTokenInteractive to acquire a token
    Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");

    try
    {
        result = await app.AcquireTokenInteractive(scopes)
                          .ExecuteAsync();
    }
    catch (MsalException msalex)
    {
        ResultText.Text = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
    }
}
catch (Exception ex)
{
    ResultText.Text = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
    return;
}

if (result != null)
{
    string accessToken = result.AccessToken;
    // Use the token
}

清除缓存

在公共客户端应用程序中,从缓存中删除帐户会将其清除。 但是,这不会删除浏览器中的会话 Cookie。

var accounts = (await app.GetAccountsAsync()).ToList();

// clear the cache
while (accounts.Any())
{
   await app.RemoveAsync(accounts.First());
   accounts = (await app.GetAccountsAsync()).ToList();
}