分享方式:


從您的應用程式連線到資源,而不需處理認證

具有受控識別支援的 Azure 資源一律會提供選項來指定受控識別,以連線到支援 Microsoft Entra 驗證的 Azure 資源。 受控識別支援可讓開發人員不需要在程式碼中管理認證。 使用支援受控識別的 Azure 資源時,受控識別是建議的驗證選項。 閱讀受控識別的概觀

此頁面示範如何設定 App Service,使其可以連線到 Azure Key Vault、Azure 儲存體和 Microsoft SQL Server。 相同的準則可以用於支援受控識別的任何 Azure 資源,以及所要連線資源支援 Microsoft Entra 驗證的任何資源。

程式碼範例會使用 Azure 身分識別用戶端程式庫,這是建議的方法,因為其會自動為您處理許多步驟,包括取得連線中使用的存取權杖。

受控識別可以連線到哪些資源?

受控識別可以連線到支援 Microsoft Entra 驗證的任何資源。 一般而言,資源不需要特殊支援,即可允許受控識別連線至其中。

某些資源不支援 Microsoft Entra 驗證,或其用戶端程式庫不支援使用權杖進行驗證。 請繼續閱讀,以了解如何使用受控識別安全地存取認證,而不需要將其儲存在程式碼或應用程式設定中。

建立受控識別

兩種受控識別:系統指派和使用者指派。 系統指派的身分識別會直接連結到單一 Azure 資源。 刪除 Azure 資源時,也會刪除身分識別。 使用者指派的受控識別可以與多個 Azure 資源相關聯,而且其生命週期與這些資源無關。

對於大多數情況,我們建議您使用使用者指派的受控識別。 如果您使用的來源資源不支援使用者指派的受控識別,則您應該參考該資源提供者的文件,了解如何將其設定為具有系統指派的受控識別。

重要

用於建立受控識別的帳戶需要「受控識別參與者」之類的角色,才能建立新的使用者指派的受控識別。

使用您偏好的選項來建立使用者指派的受控識別:

建立使用者指派的受控識別之後,請記下建立受控識別時傳回的 clientIdprincipalId 值。 您在新增權限時使用 principalId,並在應用程式的程式碼中使用 clientId

使用使用者指派的受控識別設定應用程式服務

在您可以在程式碼中使用受控識別之前,我們必須將其指派給將使用它的應用程式服務。 將應用程式服務設定為使用使用者指派的受控識別的程序要求您在應用程式設定中指定受控識別的資源識別碼

將權限新增至身分識別

將應用程式服務設定為使用使用者指派的受控識別後,向該識別授與必要的權限。 在此案例中,我們會使用此身分識別來與 Azure 儲存體互動,因此您需要使用 Azure 角色型存取控制 (RBAC) 系統,來將使用者指派的受控識別權限授與資源。

重要

您將需要「使用者存取管理員」或「擁有者」等的角色,目標資源才能新增角色指派。 請確定您授與執行應用程式所需的最低權限。

您想要存取的任何資源都需要您授與身分識別權限。 例如,若您要求權杖以存取 Key Vault,則須新增存取原則並包含該應用程式或函數的受控識別。 否則即使呼叫 Key Vault 時使用有效權杖,仍將遭拒絕。 對 Azure SQL Database 而言,也是如此。 若要深入瞭解哪些資源支援 Microsoft Entra 權杖,請參閱支援 Microsoft Entra 驗證的 Azure 服務。

在您的程式碼中使用受控識別

完成上述步驟之後,您的應用程式服務擁有具有 Azure 資源權限的受控識別。 您可以使用受控識別來取得存取權杖,您的程式碼可使用該權杖與 Azure 資源互動,而不是將認證儲存在您的程式碼中。

我們建議您針對您慣用的程式設計語言使用 Azure 身分識別程式庫。 此程式庫會為您取得存取權杖,讓您輕鬆地連線到目標資源。

深入閱讀下列 Azure 身分識別程式庫:

在開發環境中使用 Azure 身分識別程式庫

每個 Azure 身分識別程式庫都提供 DefaultAzureCredential 類型。 DefaultAzureCredential 會自動嘗試透過多個機制進行驗證,包括環境變數或互動式登入。 您可以使用自己的認證,在開發環境中使用認證類型。 其也可以利用受控識別,在 Azure 實際執行環境中使用。 當您部署應用程式時,不需要變更任何程式碼。

如果您使用的是使用者指派的受控識別,則您也應該將身分識別的用戶端識別碼當作參數傳遞,明確指定您想要使用其進行驗證的使用者指派受控識別。 您可以瀏覽至 Azure 入口網站中的身分識別來擷取用戶端識別碼。

存取 Azure 儲存體中的 Blob

using Azure.Identity;
using Azure.Storage.Blobs;

// code omitted for brevity

// Specify the Client ID if using user-assigned managed identities
var clientID = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID");
var credentialOptions = new DefaultAzureCredentialOptions
{
    ManagedIdentityClientId = clientID
};
var credential = new DefaultAzureCredential(credentialOptions);                        

var blobServiceClient1 = new BlobServiceClient(new Uri("<URI of Storage account>"), credential);
BlobContainerClient containerClient1 = blobServiceClient1.GetBlobContainerClient("<name of blob>");
BlobClient blobClient1 = containerClient1.GetBlobClient("<name of file>");

if (blobClient1.Exists())
{
    var downloadedBlob = blobClient1.Download();
    string blobContents = downloadedBlob.Value.Content.ToString();                
}

存取 Azure Key Vault 中儲存的秘密

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Core;

// code omitted for brevity

// Specify the Client ID if using user-assigned managed identities
var clientID = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID");
var credentialOptions = new DefaultAzureCredentialOptions
{
    ManagedIdentityClientId = clientID
};
var credential = new DefaultAzureCredential(credentialOptions);        

var client = new SecretClient(
    new Uri("https://<your-unique-key-vault-name>.vault.azure.net/"),
    credential);
    
KeyVaultSecret secret = client.GetSecret("<my secret>");
string secretValue = secret.Value;

存取 Azure SQL Database

using Azure.Identity;
using Microsoft.Data.SqlClient;

// code omitted for brevity

// Specify the Client ID if using user-assigned managed identities
var clientID = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID");
var credentialOptions = new DefaultAzureCredentialOptions
{
    ManagedIdentityClientId = clientID
};

AccessToken accessToken = await new DefaultAzureCredential(credentialOptions).GetTokenAsync(
    new TokenRequestContext(new string[] { "https://database.windows.net//.default" }));                        

using var connection = new SqlConnection("Server=<DB Server>; Database=<DB Name>;")
{
    AccessToken = accessToken.Token
};
var cmd = new SqlCommand("select top 1 ColumnName from TableName", connection);
await connection.OpenAsync();
SqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
    Console.WriteLine(dr.GetValue(0).ToString());
}
dr.Close();	

連線到程式庫中不支援 Microsoft Entra ID 或權杖型驗證的資源

某些 Azure 資源尚未支援 Microsoft Entra 驗證,或其用戶端程式庫不支援使用權杖進行驗證。 這些資源通常是開放原始碼技術,預期連接字串中有使用者名稱和密碼或存取金鑰。

若要避免將認證儲存在您的程式碼或應用程式設定中,您可以將認證當作祕密儲存在 Azure Key Vault 中。 使用上面顯示的範例,您可以使用受控識別從 Azure Key Vault 擷取秘密,並將認證傳遞至連接字串。 此方法表示不需要直接在您的程式碼或環境中處理認證。

如果您要直接處理權杖時的指導方針

在某些案例中,您可能會想要手動取得受控識別的權杖,而不是使用內建方法來連線到目標資源。 這些案例不包含您所用程式設計語言的用戶端程式庫,或您要連線至其中的目標資源,或所連線資源未在 Azure 上執行的目標資源。 手動取得權杖時,我們會提供下列指導方針:

快取您取得的權杖

如需效能和可靠性,建議您的應用程式快取本機記憶體中的權杖,或如果您想要將它們儲存至磁碟,請將其加密。 因為受控識別權杖的有效時間為 24 小時,所以定期要求新權杖沒有任何好處,因為快取的權杖會從權杖發行端點傳回。 如果超過要求限制,您將會受到速率限制,並收到 HTTP 429 錯誤。

當您取得權杖時,可以將您的權杖快取設定為在產生權杖時將傳回 expires_on (或對等屬性) 前 5 分鐘到期。

權杖檢查

您的應用程式不應該依賴權杖的內容。 權杖的內容僅適用於要存取的受眾 (目標資源),而不是要求權杖的用戶端。 權杖內容可能會在未來變更或加密。

請不要公開或移動權杖

權杖應該如認證般對待。 請不要將其公開給使用者或其他服務;例如,記錄/監視解決方案。 它們不應該從使用它們的來源資源移動,但針對目標資源進行驗證除外。

後續步驟