使用MSAL库配合PowerShell获取Azure DevOps令牌跨会话缓存失效问题
问题根本原因
MSAL.NET 默认将令牌缓存在当前进程的内存中,PowerShell 会话结束后内存缓存会被完全释放,因此重新打开会话后无法读取到之前的登录凭证,必须重新走交互式登录流程。
解决方案:配置MSAL持久化令牌缓存
你需要引入MSAL官方的缓存扩展组件,将令牌缓存加密存储到本地磁盘,实现跨PowerShell会话共享。
第一步:安装依赖组件
先安装MSAL缓存扩展的NuGet包:
Install-Package Microsoft.Identity.Client.Extensions.Msal -Scope CurrentUser
第二步:修改你的脚本,启用持久化缓存
修改后的完整可运行代码如下:
# 请替换为你自己的配置 $ClientId = "你的Azure AD应用注册客户端ID" $adoResourceId = "499b84ac-1321-427f-aa17-267ca6975798" # Azure DevOps官方资源ID固定为这个值 [string[]] $Scopes = "$adoResourceId/.default" # 配置持久化缓存参数 $cacheDir = Join-Path $env:USERPROFILE ".msal_cache" $cacheFileName = "ado_msal_cache.bin" if (-not (Test-Path $cacheDir)) { New-Item -ItemType Directory -Path $cacheDir | Out-Null } # 初始化缓存助手,自动处理加密存储(Windows用DPAPI,macOS用钥匙串,Linux用libsecret) $storageProperties = [Microsoft.Identity.Client.Extensions.Msal.StorageCreationPropertiesBuilder]::new($cacheFileName, $cacheDir).Build() $cacheHelper = [Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper]::CreateAsync($storageProperties).GetAwaiter().GetResult() # 构建公共客户端应用,挂载持久化缓存 [Microsoft.Identity.Client.IPublicClientApplication] $app = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($ClientId).Build() $cacheHelper.RegisterCache($app.UserTokenCache) # 获取缓存中的账户 [ContextHelper]::Account = $app.GetAccountsAsync().GetAwaiter().GetResult() | Select-Object -First 1 $tokenSource = New-Object System.Threading.CancellationTokenSource $taskAuthenticationResult = $null $result = $null try { # 优先静默获取令牌 $AquireTokenParameters = $app.AcquireTokenSilent($Scopes, [ContextHelper]::Account) $taskAuthenticationResult = $AquireTokenParameters.ExecuteAsync($tokenSource.Token) $taskAuthenticationResult.Wait() $result = $taskAuthenticationResult.Result } catch { # 静默失败则走交互式登录 $AquireTokenParameters = $app.AcquireTokenInteractive($Scopes) $taskAuthenticationResult = $AquireTokenParameters.ExecuteAsync($tokenSource.Token) $taskAuthenticationResult.Wait() $result = $taskAuthenticationResult.Result } # 输出令牌结果 Write-Host "获取到的访问令牌有效期至:$($result.ExpiresOn)"
注意事项
- 本地缓存文件默认采用当前用户身份加密,仅当前登录的系统用户可读取,不会泄露凭证
- 若需要清除登录状态,直接删除
$env:USERPROFILE\.msal_cache\ado_msal_cache.bin文件即可 - 确保你的Azure AD应用注册中已经开启了「允许公共客户端流」选项,否则交互式登录会被拦截
内容的提问来源于stack exchange,提问作者Arvind Singh
相关产品推荐
相关产品推荐

