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

基于Microsoft Identity:检查访问令牌有效性并避免MsalUiRequiredException

问题解决方案

1. 在_host.cshtml展示应用前检查访问令牌有效性

你可以利用Razor页面的服务器端逻辑,在用户加载_host.cshtml时预先验证令牌状态:

  1. 给_host.cshtml添加页面模型文件(_Host.cshtml.cs),注入ITokenAcquisition和IConfiguration:
public class HostModel : PageModel
{
    private readonly ITokenAcquisition _tokenAcquisition;
    private readonly IConfiguration _configuration;
    private readonly string[] _sharepointScopes;

    public HostModel(ITokenAcquisition tokenAcquisition, IConfiguration configuration)
    {
        _tokenAcquisition = tokenAcquisition;
        _configuration = configuration;
        _sharepointScopes = _configuration.GetSection("SharepointScopes").Get<string[]>();
    }

    public async Task OnGetAsync()
    {
        try
        {
            // 尝试获取令牌(MSAL会自动检查缓存,过期则用刷新令牌静默刷新)
            await _tokenAcquisition.GetAccessTokenForUserAsync(_sharepointScopes);
        }
        catch (MsalUiRequiredException)
        {
            // 触发重新认证,让用户重新登录获取有效令牌
            await HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
        }
    }
}
  1. 在_host.cshtml顶部指定页面模型:
@page "/"
@model HostModel
@{
    Layout = null;
}

这样用户访问应用时,会先执行OnGetAsync方法验证令牌,无效则直接触发重新认证,避免后续组件调用API时出错。

2. 用户会话期间防止访问令牌过期的方法

(1)依赖MSAL自动刷新机制

MSAL默认会在访问令牌过期前,使用刷新令牌静默获取新的访问令牌。确保你的配置满足:

  • 已正确配置AddDistributedTokenCaches()(比如用Redis、SQL Server缓存),避免令牌缓存丢失导致无法刷新
  • 应用在Azure AD中已获得offline_access权限(默认EnableTokenAcquisitionToCallDownstreamApi会包含这个范围,可检查Azure AD应用的API权限)

(2)定期静默刷新令牌

在Blazor Server的全局组件(比如MainLayout.razor)中,添加定时任务,定期调用GetAccessTokenForUserAsync触发静默刷新:

@inject ITokenAcquisition TokenAcquisition
@inject IConfiguration Configuration
@implements IDisposable

private Timer _refreshTimer;
private string[] _sharepointScopes;

protected override async Task OnInitializedAsync()
{
    _sharepointScopes = Configuration.GetSection("SharepointScopes").Get<string[]>();
    // 每50分钟刷新一次(访问令牌默认有效期60分钟)
    _refreshTimer = new Timer(async _ => await RefreshTokenAsync(), null, TimeSpan.Zero, TimeSpan.FromMinutes(50));
}

private async Task RefreshTokenAsync()
{
    try
    {
        await TokenAcquisition.GetAccessTokenForUserAsync(_sharepointScopes);
    }
    catch (MsalUiRequiredException)
    {
        // 这里可以记录日志,或者提示用户重新登录
    }
}

public void Dispose()
{
    _refreshTimer?.Dispose();
}

(3)优化令牌获取逻辑

在你的SharepointClientFactory中,不要用同步阻塞的.GetAwaiter().GetResult(),改用异步方式(Blazor Server支持异步事件处理):

ClientContext SharepointClientFactory()
{
    var clientContext = new ClientContext(siteUrl);

    clientContext.ExecutingWebRequest += async (sender, e) =>
    {
        try
        {
            string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes: effectiveScopes);
            e.WebRequestExecutor.RequestHeaders.Add("Authorization", $"Bearer {accessToken}");
        }
        catch (MicrosoftIdentityWebChallengeUserException ex)
        {
            // 触发导航到登录页面
            NavigationManager.NavigateTo("/MicrosoftIdentity/Account/SignIn", forceLoad: true);
        }
    };

    return clientContext;
}

同步阻塞可能导致MSAL无法正确处理令牌刷新流程,改用异步能确保静默刷新正常执行。

(4)调整Azure AD令牌生命周期

如果业务允许,可以在Azure AD门户中延长访问令牌的有效期(最长可设置为1天),减少过期频率:

  • 进入Azure AD -> 应用注册 -> 你的应用 -> 令牌配置 -> 添加策略,设置访问令牌的生命周期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:52:56