適用於 .NET 的 Azure 身分識別程式庫中的認證鏈
Azure 身分識別程式庫提供認證 - 從 Azure 核心程式庫的 TokenCredential 類別衍生出的公用類別。 認證代表從 Microsoft Entra ID 取得存取權杖的不同驗證流程。 這些認證可以鏈結在一起,形成一個經過排序的驗證機制以進行嘗試。
鏈結認證的運作方式
在執行階段,認證鏈會嘗試使用序列的第一個憑證進行驗證。 如果該認證無法取得存取權杖,則會嘗試序列中的下一個認證,以此類推,直到成功取得存取權杖為止。 以下序列圖表說明這項行為:
為什麼使用認證鏈結
鏈結認證可以提供以下優點:
環境感知:根據應用程式執行所在的環境,自動選取最適當的認證。 如果沒有它,您必須撰寫如以下的程式碼:
TokenCredential credential; if (app.Environment.IsProduction() || app.Environment.IsStaging()) { credential = new ManagedIdentityCredential(clientId: userAssignedClientId); } else { // local development environment credential = new VisualStudioCredential(); }
順暢轉換:您的應用程式可以在不變更驗證碼的情況下,從本機開發移至預備或生產環境。
提升復原能力:包含一個後援機制,在前一個認證無法取得存取權杖時移至下一個認證。
如何選擇鏈結認證
認證鏈結有兩種不同的原理:
- 「卸除式」鏈結:從預先設定的鏈結開始,然後排除不需要的部分。 針對這個方法,請參閱 DefaultAzureCredential 概觀一節。
- 「建置式」鏈結:從空的鏈結開始,然後只包含需要的部分。 針對這個方法,請參閱 ChainedTokenCredential 概觀一節。
DefaultAzureCredential 概觀
DefaultAzureCredential 是固有、預先設定的認證鏈結。 其設計目的是支援多種環境,以及最常見的驗證流程和開發人員工具。 在圖形化表單中,基礎的鏈結看起來如下:
DefaultAzureCredential
嘗試認證時依照的順序。
順序 | 認證 | 描述 | 預設啟用? |
---|---|---|---|
1 | 環境 | 讀取環境變數集合,以判斷應用程式服務主體(應用程式使用者)是否已為應用程式設定。 如是,DefaultAzureCredential 則會使用這些值向 Azure 驗證應用程式。 此方法最常用於伺服器環境,但也可在本機開發時使用。 |
Yes |
2 | 工作負載身分識別 | 如果應用程式部署到已啟用工作負載身分識別的 Azure 主機,請驗證該帳戶。 | Yes |
3 | 受控識別 | 如果應用程式部署到已啟用受控識別的 Azure 主機,則使用該受控識別將應用程式驗證至 Azure。 | Yes |
4 | Visual Studio | 如果開發人員透過登錄到 Visual Studio 驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 | Yes |
5 | Azure CLI | 如果開發人員使用 Azure CLI 的 az login 命令驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 |
Yes |
6 | Azure PowerShell | 如果開發人員使用 Azure PowerShell 的 Connect-AzAccount cmdlet 驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 |
Yes |
7 | Azure Developer CLI | 如果開發人員使用 Azure Developer CLI 的 azd auth login 命令驗證至 Azure,請使用該帳戶進行驗證。 |
Yes |
8 | 互動式瀏覽器 | 如果啟用,則透過目前系統的預設瀏覽器以互動方式驗證開發人員。 | No |
在最簡單的形式中,您可以使用 DefaultAzureCredential
的無參數版本,如下所示:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
});
提示
UseCredential
建議使用上述代碼段中的方法,以用於 ASP.NET Core 應用程式。 如需詳細資訊,請參閱 在 ASP.NET Core 應用程式中使用 Azure SDK for .NET。
如何自訂 DefaultAzureCredential
若要從 DefaultAzureCredential
移除認證,使用 DefaultAzureCredentialOptions 中相應的 Exclude
前置屬性。 例如:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new DefaultAzureCredential(
new DefaultAzureCredentialOptions
{
ExcludeEnvironmentCredential = true,
ExcludeWorkloadIdentityCredential = true,
ManagedIdentityClientId = userAssignedClientId,
}));
});
在上述程式碼範例中,從認證鏈結中移除 EnvironmentCredential
和 WorkloadIdentityCredential
。 因此,第一個嘗試的認證是 ManagedIdentityCredential
。 修改後的鏈結看起來如下:
注意
InteractiveBrowserCredential
預設為排除 ,因此沒有顯示在上列圖表中。 若要包含 InteractiveBrowserCredential
,請傳遞 true
至建構函式 DefaultAzureCredential(Boolean) 或將 屬性 DefaultAzureCredentialOptions.ExcludeInteractiveBrowserCredential 設定為 false
。
由於更多的 Exclude
前置屬性設定為 true
(已設定排除認證),使用 DefaultAzureCredential
的優點將會降低。 在這種情況下,ChainedTokenCredential
是比較好的選擇,且需要較少的程序碼。 為了方便說明,這兩個程式碼範例有相同的行為:
credential = new DefaultAzureCredential(
new DefaultAzureCredentialOptions
{
ExcludeEnvironmentCredential = true,
ExcludeWorkloadIdentityCredential = true,
ExcludeAzureCliCredential = true,
ExcludeAzurePowerShellCredential = true,
ExcludeAzureDeveloperCliCredential = true,
ManagedIdentityClientId = userAssignedClientId
});
ChainedTokenCredential 概觀
ChainedTokenCredential 是一個空的鏈結,您可以根據自己的應用程式需求加入認證。 例如:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new ChainedTokenCredential(
new ManagedIdentityCredential(clientId: userAssignedClientId),
new VisualStudioCredential()));
});
上述程式碼範例將建立由兩個認證組成的自訂認證鏈結。 如有必要,會先嘗試的使用者指派的 ManagedIdentityCredential
的受控識別變體,然後嘗試 VisualStudioCredential
。 在圖形化表單中,鏈結看起來如下:
提示
為提升效能,請根據您的生產環境將 ChainedTokenCredential
中的認證順序最佳化。 要用於本機開發環境的認證應該在最後加入。
DefaultAzureCredential 的使用方式指導
DefaultAzureCredential
無疑是開始使用 Azure 身分識別程式庫的最簡單方式,但這樣的便利性有所取捨。 將應用程式部署至 Azure 之後,您應該了解應用程式的驗證需求。 基於這個理由,強烈建議您從 DefaultAzureCredential
改用下列其中一個解決方案:
- 特定的
TokenCredential
實作,例如ManagedIdentityCredential
。 如需其他方式的資訊,請參閱衍生清單 。 - 針對您執行應用程式的 Azure 環境最佳化的簡化
ChainedTokenCredential
實作。
原因如下:
- 偵錯困難:當驗證失敗時,偵錯和找出不符規定的認證可能會很困難。 您必須啟用記錄,才能逐一查看每個認證的進展,以及每個認證的成功/失敗狀態。 如需詳細資訊,請參閱偵錯鏈結認證。
- 過度效能負荷:循序嘗試多個認證的過程可能會造成效能負荷。 例如,在本機開發電腦上執行時,無法使用受控識別。 因此,
ManagedIdentityCredential
在本機開發環境中會總是失敗,除非透過相應的Exclude
前置屬性明確停用。 - 無法預測的行為:
DefaultAzureCredential
會檢查特定環境變數是否存在。 有人可能會在主機電腦上的系統層級新增或修改這些環境變數。 這些變更會全域套用,並因此改變DefaultAzureCredential
在該電腦上執行的所有應用程式中的執行階段行為。
偵錯鏈結認證
若要診斷意外的問題,或是了解鏈結認證正在執行的動作,請在您的應用程式中啟用記錄。 或者,也可以篩選記錄,僅顯示從 Azure 身分識別程式庫發出的事件。 例如:
using AzureEventSourceListener listener = new((args, message) =>
{
if (args is { EventSource.Name: "Azure-Identity" })
{
Console.WriteLine(message);
}
}, EventLevel.LogAlways);
為供說明之用,假設 DefaultAzureCredential
的無參數形式是用來驗證 Log Analytics 工作區的要求。 應用程式是在本機開發環境中執行,且 Visual Studio 已驗證至 Azure 帳戶。 在下次應用程式執行時,輸出結果會顯示下列相關項目:
DefaultAzureCredential.GetToken invoked. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342
EnvironmentCredential.GetToken invoked. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342
EnvironmentCredential.GetToken was unable to retrieve an access token. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342 Exception: Azure.Identity.CredentialUnavailableException (0x80131500): EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
WorkloadIdentityCredential.GetToken invoked. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342
WorkloadIdentityCredential.GetToken was unable to retrieve an access token. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342 Exception: Azure.Identity.CredentialUnavailableException (0x80131500): WorkloadIdentityCredential authentication unavailable. The workload options are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/workloadidentitycredential/troubleshoot
ManagedIdentityCredential.GetToken invoked. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342
ManagedIdentityCredential.GetToken was unable to retrieve an access token. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342 Exception: Azure.Identity.CredentialUnavailableException (0x80131500): ManagedIdentityCredential authentication unavailable. No response received from the managed identity endpoint.
VisualStudioCredential.GetToken invoked. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342
VisualStudioCredential.GetToken succeeded. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342 ExpiresOn: 2024-08-13T17:16:50.8023621+00:00
DefaultAzureCredential credential selected: Azure.Identity.VisualStudioCredential
DefaultAzureCredential.GetToken succeeded. Scopes: [ https://api.loganalytics.io//.default ] ParentRequestId: d7ef15d1-50f8-451d-afeb-6b06297a3342 ExpiresOn: 2024-08-13T17:16:50.8023621+00:00
在上列輸出結果中,請注意:
EnvironmentCredential
、WorkloadIdentityCredential
和ManagedIdentityCredential
(按照順序) 皆無法取得 Microsoft Entra 存取權杖。DefaultAzureCredential credential selected:
前置的項目表示已選取的認證,在此案例中為VisualStudioCredential
。 因為VisualStudioCredential
已成功,所以之後未使用任何認證。