.NET MAUI中使用MSAL:如何避免重启已登录应用后需UI获取访问令牌
Windows 11平台MAUI应用MSAL令牌缓存重启丢失的解决方法
问题核心是:Windows平台MAUI应用默认使用内存级令牌缓存,重启应用后缓存会被清空;而Android平台MSAL有默认的持久化缓存实现,所以无此问题。以下是具体解决步骤:
1. 实现自定义令牌缓存持久化
通过将MSAL令牌缓存序列化到应用私有本地文件,实现重启后缓存保留。
步骤1:编写缓存序列化助手类
public static class TokenCacheHelper { // 缓存文件存储路径(Windows应用私有目录) private static readonly string _cacheFilePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "msal_token_cache.bin"); // 配置缓存序列化回调 public static void EnableSerialization(ITokenCache tokenCache) { tokenCache.SetBeforeAccess(BeforeAccessNotification); tokenCache.SetAfterAccess(AfterAccessNotification); } // 读取缓存文件并反序列化 private static void BeforeAccessNotification(TokenCacheNotificationArgs args) { if (File.Exists(_cacheFilePath)) { args.TokenCache.DeserializeMsalV3(File.ReadAllBytes(_cacheFilePath)); } } // 缓存变更后写入文件 private static void AfterAccessNotification(TokenCacheNotificationArgs args) { if (args.HasStateChanged) { File.WriteAllBytes(_cacheFilePath, args.TokenCache.SerializeMsalV3()); } } }
步骤2:初始化PublicClientApplication时绑定缓存
var pca = PublicClientApplicationBuilder .Create("你的客户端ID") .WithRedirectUri("msal-你的客户端ID://auth") .Build(); // 启用自定义缓存序列化 TokenCacheHelper.EnableSerialization(pca.UserTokenCache);
2. 可选:加密缓存文件(增强安全性)
令牌包含敏感信息,可使用Windows数据保护API加密缓存文件:
public static class TokenCacheHelper { private static readonly string _cacheFilePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "msal_token_cache.bin"); private static readonly DataProtectionProvider _dataProtector = new DataProtectionProvider(); public static void EnableSerialization(ITokenCache tokenCache) { tokenCache.SetBeforeAccess(BeforeAccessNotification); tokenCache.SetAfterAccess(AfterAccessNotification); } private static void BeforeAccessNotification(TokenCacheNotificationArgs args) { if (File.Exists(_cacheFilePath)) { using var fileStream = new FileStream(_cacheFilePath, FileMode.Open); using var protectedStream = _dataProtector.UnprotectStream(fileStream); var encryptedBytes = new byte[protectedStream.Length]; protectedStream.Read(encryptedBytes, 0, encryptedBytes.Length); args.TokenCache.DeserializeMsalV3(encryptedBytes); } } private static void AfterAccessNotification(TokenCacheNotificationArgs args) { if (args.HasStateChanged) { using var fileStream = new FileStream(_cacheFilePath, FileMode.Create); using var protectedStream = _dataProtector.ProtectStream(fileStream); var cacheBytes = args.TokenCache.SerializeMsalV3(); protectedStream.Write(cacheBytes, 0, cacheBytes.Length); } } }
3. 额外检查点
- 确保使用最新稳定版的Microsoft.Identity.Client包,旧版本可能存在Windows平台缓存处理bug。
- Windows应用无需额外权限,
LocalApplicationData是应用私有目录,默认允许读写。
内容的提问来源于stack exchange,提问作者Ignotus
相关产品推荐
相关产品推荐

