適用於 Java 的 Azure 身分識別連結庫中的認證鏈結
Azure 身分識別程式庫提供 憑證—實作 Azure Core 程式庫 TokenCredential 介面的公用類別。 凭證代表從 Microsoft Entra ID 取得存取權杖的獨特驗證流程。 這些認證可以鏈結在一起,形成一個經過排序的驗證機制以進行嘗試。
鏈結認證的運作方式
在執行階段,認證鏈會嘗試使用序列的第一個憑證進行驗證。 如果該認證無法取得存取權杖,則會嘗試序列中的下一個認證,以此類推,直到成功取得存取權杖為止。 以下序列圖表說明這項行為:
為什麼使用認證鏈結
鏈結認證可以提供以下優點:
環境感知:根據應用程式執行所在的環境,自動選取最適當的認證。 如果沒有它,您必須撰寫如以下的程式碼:
import com.azure.core.credential.TokenCredential; import com.azure.identity.AzureCliCredentialBuilder; import com.azure.identity.ManagedIdentityCredentialBuilder; // Code omitted for brevity TokenCredential credential = null; // Set up credential based on environment (Azure or local development) String environment = System.getenv("ENV"); if (environment != null && environment.equals("production")) { credential = new ManagedIdentityCredentialBuilder() .clientId(userAssignedClientId) .build(); } else { credential = new AzureCliCredentialBuilder() .build(); }
順暢轉換:您的應用程式可以在不變更驗證碼的情況下,從本機開發移至預備或生產環境。
提升彈性:包含一個後援機制,在前一個憑證無法取得存取權杖時會移至下一個憑證。
如何選擇鏈結認證
認證鏈結有兩種不同的原理:
- 使用預先設定的鏈結:從符合最常見驗證案例的有意見、預先建構的鏈結開始。 針對這個方法,請參閱 DefaultAzureCredential 概觀一節。
- 「建立」鏈條:從空的鏈條開始,只包含需要的部分。 針對這個方法,請參閱 ChainedTokenCredential 概觀一節。
DefaultAzureCredential 概觀
DefaultAzureCredential 是一個具特定配置、預先設定的憑證鏈。 其設計目的是支援多種環境,以及最常見的驗證流程和開發人員工具。 在圖形形式中,底層鏈條看起來如下:
DefaultAzureCredential
嘗試驗證資料時遵循的順序。
順序 | 認證 | 描述 |
---|---|---|
1 | 環境 | 讀取環境變數集合,以判斷應用程式服務主體(應用程式使用者)是否已為應用程式設定。 如是,DefaultAzureCredential 則會使用這些值向 Azure 驗證應用程式。 此方法最常用於伺服器環境,但也可在本機開發時使用。 |
2 | 工作負載身分識別 | 如果應用程式部署到已啟用工作負載身分識別的 Azure 主機,請驗證該帳戶。 |
3 | 受控識別 | 如果應用程式部署到已啟用受控識別的 Azure 主機,則使用該受控識別將應用程式驗證至 Azure。 |
4 | 共用令牌快取 | 如果開發人員透過登錄到 Visual Studio 驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 (僅限 Windows.) |
5 | IntelliJ | 如果開發人員透過適用於 IntelliJ 的 Azure 工具組進行驗證,請驗證該帳戶。 |
6 | Azure CLI | 如果開發人員使用 Azure CLI 的 az login 命令驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 |
7 | Azure PowerShell | 如果開發人員使用 Azure PowerShell 的 Connect-AzAccount cmdlet 驗證至 Azure,請使用相同帳戶向 Azure 驗證應用程式。 |
8 | Azure Developer CLI | 如果開發人員使用 Azure Developer CLI 的 azd auth login 命令驗證至 Azure,請使用該帳戶進行驗證。 |
在最簡單的形式中,您可以使用 DefaultAzureCredential
的無參數版本,如下所示:
import com.azure.identity.DefaultAzureCredential;
import com.azure.identity.DefaultAzureCredentialBuilder;
// Code omitted for brevity
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.build();
ChainedTokenCredential 概觀
ChainedTokenCredential 是一個空的鏈結,您可以根據自己的應用程式需求加入認證。 例如:
import com.azure.identity.AzureCliCredential;
import com.azure.identity.AzureCliCredentialBuilder;
import com.azure.identity.ChainedTokenCredential;
import com.azure.identity.ChainedTokenCredentialBuilder;
import com.azure.identity.IntelliJCredential;
import com.azure.identity.IntelliJCredentialBuilder;
// Code omitted for brevity
AzureCliCredential cliCredential = new AzureCliCredentialBuilder()
.build();
IntelliJCredential ijCredential = new IntelliJCredentialBuilder()
.build();
ChainedTokenCredential credential = new ChainedTokenCredentialBuilder()
.addLast(cliCredential)
.addLast(ijCredential)
.build();
上述程式碼範例會建立一條由兩個開發用認證組成的客製化認證鏈。 先嘗試 AzureCliCredential
,然後視需要 IntelliJCredential
。 在圖形形式中,鏈條看起來如下:
提示
為了提升效能,請優化 ChainedTokenCredential
中的認證排序,按照從最常使用到最少使用的順序排列。
DefaultAzureCredential 的使用方式指導
DefaultAzureCredential
無疑是開始使用 Azure 身分識別庫的最簡單方式,但這種便利性伴隨著一些取捨。 將應用程式部署至 Azure 之後,您應該了解應用程式的驗證需求。 因此,請將 DefaultAzureCredential
取代為特定的 TokenCredential
實作,例如 ManagedIdentityCredential
。
原因如下:
- 偵錯困難:當驗證失敗時,偵錯和找出不符規定的認證可能會很困難。 您必須啟用記錄,才能逐一查看每個認證的進展,以及每個認證的成功/失敗狀態。 如需詳細資訊,請參閱偵錯鏈結認證。
-
過度效能負荷:循序嘗試多個認證的過程可能會造成效能負荷。 例如,在本機開發電腦上執行時,無法使用受控識別。 因此,
ManagedIdentityCredential
總是在本機開發環境中失敗。 -
無法預測的行為:
DefaultAzureCredential
會檢查特定環境變數是否存在。 有人可能會在主機電腦上的系統層級新增或修改這些環境變數。 這些變更會全域套用,並因此改變DefaultAzureCredential
在該電腦上執行的所有應用程式中的執行階段行為。
偵錯鏈結認證
若要診斷意外問題,或是了解連鎖憑證正在執行的操作,請在您的應用程式中啟用記錄。
為了說明目的,假設的無參數形式 DefaultAzureCredential
是用來向 Blob 記憶體帳戶驗證要求。 應用程式會在本機開發環境中執行,開發人員使用 Azure CLI 向 Azure 進行驗證。 應用程式執行時,輸出中會出現以下相關條目:
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential EnvironmentCredential is unavailable.
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential WorkloadIdentityCredential is unavailable.
[ForkJoinPool.commonPool-worker-1] WARN com.microsoft.aad.msal4j.ConfidentialClientApplication - [Correlation ID: aaaa0000-bb11-2222-33cc-444444dddddd] Execution of class com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier failed: java.util.concurrent.ExecutionException: com.azure.identity.CredentialUnavailableException: ManagedIdentityCredential authentication unavailable. Connection to IMDS endpoint cannot be established.
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential ManagedIdentityCredential is unavailable.
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential SharedTokenCacheCredential is unavailable.
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential IntelliJCredential is unavailable.
[main] INFO com.azure.identity.ChainedTokenCredential - Azure Identity => Attempted credential AzureCliCredential returns a token
在上列輸出結果中,請注意:
-
EnvironmentCredential
、WorkloadIdentityCredential
、ManagedIdentityCredential
、SharedTokenCacheCredential
和IntelliJCredential
每個都無法依該順序取得Microsoft Entra 存取令牌。 - 呼叫
AzureCliCredential.getToken
會成功,如以returns a token
為後綴的項目所指示。 因為AzureCliCredential
成功,所以未嘗試其他認證。