ASP.NET Core 3.1应用重启后Microsoft Graph访问令牌丢失如何解决
问题根因
你遇到的应用重启后令牌丢失、用户仍处于登录状态但无法调用Graph API的问题,核心原因是microsoft-identity-web库默认使用内存令牌缓存,应用重启后内存缓存被清空,仅保留了存储用户登录态的Cookie,但缓存中无可用的访问令牌、刷新令牌,因此无法直接调用下游API。
解决方案
1. 替换默认内存缓存为持久化分布式缓存
将令牌缓存存储到非内存的持久化介质中,应用重启后缓存不会丢失,无需用户重新走授权流程。配置代码如下(Program.cs/Startup.cs):
// 开发环境可先用分布式内存缓存验证逻辑,生产环境替换为Redis、数据库等持久化分布式缓存即可 services.AddDistributedMemoryCache(); services.AddMicrosoftIdentityWebAppAuthentication(Configuration) .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" }) // 启用分布式令牌缓存,替换默认的内存缓存 .AddDistributedTokenCaches() // 注入自动处理令牌的GraphServiceClient,无需手动处理AccessToken获取逻辑 .AddMicrosoftGraph(options => { options.Scopes = "user.read"; });
2. 简化控制器代码
调整后的控制器无需手动获取AccessToken,GraphServiceClient会自动处理令牌获取、刷新逻辑,异常处理也更简洁:
private readonly GraphServiceClient _graphServiceClient; public HomeController(GraphServiceClient graphServiceClient) { _graphServiceClient = graphServiceClient; } [HttpGet] [AuthorizeForScopes(Scopes = new string[] {"user.read"})] public async Task<IActionResult> A() { User user = await _graphServiceClient.Me.Request().GetAsync(); Serilog.Log.Debug("{@User}", user); return View(); }
如果令牌失效,中间件会自动捕获MsalUiRequiredException并发起授权挑战,优先用当前用户的登录Cookie静默获取新令牌,无需用户输入凭据即可完成令牌刷新。
调试方法
你遇到的断点不生效问题,是因为抛出的MsalUiRequiredException会被身份验证中间件提前捕获处理,不会运行到你设置断点的throw语句之后的逻辑,可按以下方式调试:
- 配置调试器异常捕获规则:在Visual Studio的「异常设置」面板中,搜索
Microsoft.Identity.Web、Microsoft.Identity.Client相关异常,全部勾选「当抛出时中断」,即可在异常抛出第一时间断住,查看上下文信息。 - 开启身份库日志:在appsettings.json中添加日志配置,输出完整的令牌流转、授权挑战日志:
{ "Logging": { "LogLevel": { "Microsoft.Identity.Web": "Debug", "Microsoft.Identity.Client": "Debug", "Microsoft.Authentication": "Debug" } } }
日志中会清晰展示令牌获取失败原因、跳转授权地址的生成逻辑。
- 抓包验证跳转逻辑:用浏览器开发者工具的「网络」面板抓请求,可查看302跳转的授权地址参数,确认是否为静默授权(参数包含
prompt=none即为静默授权,无需用户交互)。
内容的提问来源于stack exchange,提问作者Wayne
相关产品推荐
相关产品推荐

