問題描述

Web App 調用 Azure Entra ID 中國區認證端點 login.chinacloudapi.cn 獲取訪問令牌時,產生了異常巨大的 Entra ID 請求量,最終導致請求失敗和整體登錄不穩定。

問題發生在使用 MSAL 的 AcquireTokenForClient 獲取 Token 場景中,表面現象是“Web App 調用 Entra ID 失敗”,實質原因則與令牌緩存未生效密切相關。

 

問題解答

Web App 使用的是 Client Credentials Flow(客户端憑據模式),核心實現依賴 MSAL 的 ConfidentialClientApplication 與 AcquireTokenForClient 方法。

優化後的關鍵代碼如下(原文代碼):

var app = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecret)
        .WithAuthority(new Uri(authority))
        .WithLegacyCacheCompatibility(false)
        .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
        .Build();

以及在獲取訪問令牌時:

await app.AcquireTokenForClient(scopes).ExecuteAsync();

圍繞上述代碼,AcquireTokenForClient 獲取 Token 的完整流程可以拆解為以下幾個關鍵點:

 一:ConfidentialClientApplication 是 Token 緩存的承載者

ConfidentialClientApplication 表示 Web App 自身在 Azure Entra ID中的“應用身份”,它不僅負責向 Entra ID發起認證請求,同時內部維護了 MSAL 的訪問令牌緩存。如果該對象被頻繁創建或生命週期過短,緩存將無法複用,直接導致每次獲取 token 都訪問 Entra ID。

 

二:WithCacheOptions(CacheOptions.EnableSharedCacheOptions) 的核心作用

.WithCacheOptions(CacheOptions.EnableSharedCacheOptions)

這行代碼的意義在於:

  • 顯式啓用 Shared Token Cache
  • 允許同一應用實例在多個 token 請求之間共享並複用已獲取的 access token
  • 在 token 有效期內,MSAL 會優先從緩存返回 token,而不是訪問 Entra ID

缺少該配置,或未正確複用 app 對象時,即使使用了 MSAL,也相當於每次 AcquireTokenForClient 都是一次全新的登錄請求。

 

三:AcquireTokenForClient 的真實執行邏輯

當調用以下代碼時:

await app.AcquireTokenForClient(scopes).ExecuteAsync();

MSAL 實際執行順序為:

1:在本地緩存中查找匹配 scopes 的 access token
2:如果 token 存在且未過期 → 直接返回(不調用 AAD (Entra ID))
3:如果不存在或已過期 → 才向 login.chinacloudapi.cn 發起一次新的 token 請求
4:將新 token 寫入緩存,供後續請求複用

 

四:最後,正確的方式是

  • 應用級別(如 Startup / Singleton)創建一次 ConfidentialClientApplication
  • 啓用 .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
  • 所有業務代碼統一調用 AcquireTokenForClient 獲取 token

 通過該方式,可以顯著降低對 Azure Entra ID的請求壓力,避免登錄風暴,並提升 Web App 的穩定性。

 

參考資料 

MSAL Token Cache 説明 :https://learn.microsoft.com/en-us/entra/identity-platform/msal-acquire-cache-tokens#acquiring-tokens 



當在複雜的環境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 雲中,恰是如此!