You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure认证获取的访问令牌如何刷新?避免用户频繁登录

问题描述

我在Azure App Service中有一段HomeController初始化代码如下:

public HomeController(ILogger<HomeController> logger, GraphServiceClient graphServiceClient, ITokenAcquisition tokenAcquisition)
{
    var task = Task.Run(async () => await tokenAcquisition.GetAuthenticationResultForUserAsync(new[] { "some.allowed.scope" }));
    var context = task.Result;
    var accessToken = context.AccessToken;
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    client.DefaultRequestHeaders.Add("FeatureFlag", "00000004");
    var newGraphClient = new GraphServiceClient(client);
}

当前访问令牌可正常用于GraphServiceClient,但令牌约1小时后过期。我的服务需要在不打扰用户的情况下定期操作Azure账户,请问如何避免用户频繁登录?


解决方案

1. 利用刷新令牌自动续期访问令牌

通过GetAuthenticationResultForUserAsync获取的AuthenticationResult包含刷新令牌(Refresh Token),有效期通常为90天,可用于在访问令牌过期时自动获取新令牌,无需用户交互。核心要点:

  • 必须确保申请的权限包含offline_access,否则无法获取刷新令牌
  • 持久化加密存储刷新令牌(如Azure SQL、Cosmos DB或加密配置),关联用户标识
  • 借助MSAL的自动刷新机制,无需手动处理令牌过期逻辑

修改后的异步规范代码示例(避免构造函数同步阻塞):

private readonly ITokenAcquisition _tokenAcquisition;
private readonly GraphServiceClient _graphServiceClient;

public HomeController(ILogger<HomeController> logger, GraphServiceClient graphServiceClient, ITokenAcquisition tokenAcquisition)
{
    _tokenAcquisition = tokenAcquisition;
    _graphServiceClient = graphServiceClient;
}

public async Task<IActionResult> ExecuteBackgroundTask()
{
    try
    {
        // MSAL会自动检查令牌有效期,过期则用刷新令牌获取新令牌
        var authResult = await _tokenAcquisition.GetAuthenticationResultForUserAsync(new[] { "some.allowed.scope", "offline_access" });
        
        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        httpClient.DefaultRequestHeaders.Add("FeatureFlag", "00000004");
        var graphClient = new GraphServiceClient(httpClient);

        // 执行你的Graph操作
        await graphClient.Me.Messages.Request().GetAsync();
    }
    catch (MsalUiRequiredException)
    {
        // 刷新令牌也已过期,需引导用户重新登录
        return Challenge();
    }
    return Ok();
}

2. 结合后台服务处理定期任务

若需在用户不活跃时执行周期性操作,使用**ASP.NET Core后台服务(IHostedService)**配合持久化刷新令牌:

  1. 用户登录时,将刷新令牌与用户ID关联加密存储
  2. 后台服务定时读取待处理用户的刷新令牌,调用MSAL获取有效访问令牌
  3. 执行Graph操作后,更新存储的刷新令牌(每次刷新可能返回新的刷新令牌)

3. 切换至客户端凭据流(无用户上下文场景)

如果操作无需用户个人上下文(如访问租户级资源),直接使用应用身份获取令牌,完全无需用户参与:

  • 在Azure AD应用注册中添加应用权限(而非委托权限)并授予管理员同意
  • 使用ConfidentialClientApplication获取应用令牌:
var clientId = "你的应用ID";
var clientSecret = "你的应用密钥";
var tenantId = "你的租户ID";
var scopes = new[] { "https://graph.microsoft.com/.default" };

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(clientSecret)
    .WithTenantId(tenantId)
    .Build();

var authResult = await app.AcquireTokenForClient(scopes).ExecuteAsync();
var graphClient = new GraphServiceClient(
    new DelegateAuthenticationProvider(request =>
    {
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        return Task.CompletedTask;
    }));

此方式令牌有效期同样为1小时,但MSAL会自动刷新,且全程无需用户交互。


关键注意事项

  • 令牌缓存持久化:实现ITokenCacheProvider来持久化MSAL令牌缓存,减少重复请求
  • 异步规范:禁止在构造函数中使用Task.Run+.Result,避免线程死锁,改用异步Action或初始化方法
  • 安全存储:刷新令牌为敏感信息,必须加密存储,禁止明文保存
  • 权限管理:根据实际场景选择委托权限(用户上下文)或应用权限(无用户上下文)

内容的提问来源于stack exchange,提问作者OGP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 05:20:52