本文提供指導方針,可協助您在向 Azure 服務驗證時,將 JavaScript 和 TypeScript 應用程式的效能和可靠性最大化。 若要充分利用適用於 JavaScript 的 Azure 身分識別連結庫,請務必瞭解潛在問題和緩和技術。
在生產環境中使用決定性認證
DefaultAzureCredential 是開始使用 Azure 身分識別連結庫的最平易近人的方法,但這種便利性也會帶來某些取捨。 最值得注意的是,鏈結中成功且用於要求驗證的特定認證無法事先保證。 在生產環境中,這種不可預測性可能會帶來重大且有時微妙的問題。
例如,請考慮下列假設的事件序列:
- 組織的安全性小組會授權所有應用程式使用受控識別向 Azure 資源進行驗證。
- 幾個月來,裝載在 Azure 虛擬機 (VM) 上的 JavaScript 應用程式已成功透過
DefaultAzureCredential受控識別進行驗證。 - 若未告知支援小組,開發人員會在該 VM 上安裝 Azure CLI,並執行
az login命令來向 Azure 進行驗證。 - 由於 Azure 環境中的這項新的個別組態變更,透過原始受控識別的驗證會意外開始以無訊息方式失敗。
-
DefaultAzureCredential會略過失敗的ManagedIdentityCredential,並搜尋下一個可用的認證,也就是AzureCliCredential。 - 應用程式會開始使用 Azure CLI 認證,而不是受控識別,這可能會失敗,或導致非預期的提高或降低許可權。
若要避免生產應用程式中這類細微的問題或無聲失敗,請將 DefaultAzureCredential 替換為特定的 TokenCredential 實作,例如 ManagedIdentityCredential。 如需可用的認證 ,請參閱 Azure 身分識別客戶端連結庫檔 。
例如,請考慮 Express.js 專案中的下列 DefaultAzureCredential 組態:
import { DefaultAzureCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";
const credential = new DefaultAzureCredential();
const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);
const blobServiceClient = new BlobServiceClient(
"https://storageAccountName.blob.core.windows.net",
credential
);
修改上述程式代碼,根據應用程式執行所在的環境選取認證:
import { AzureDeveloperCliCredential, ManagedIdentityCredential, ChainedTokenCredential,
AzureCliCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";
let credential;
// In production, use only ManagedIdentityCredential
if (process.env.NODE_ENV === 'production') {
// For user-assigned managed identity, provide the client ID
credential = new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID);
}
// In development, use a chain of credentials appropriate for local work
else {
credential = new ChainedTokenCredential(
new AzureCliCredential(),
new AzureDeveloperCliCredential()
);
}
// Initialize Key Vault client
const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);
// Initialize Blob Storage client
const blobServiceClient = new BlobServiceClient(
"https://storageAccountName.blob.core.windows.net",
credential
);
在此範例中,只有 ManagedIdentityCredential 用於生產環境。 然後,本機開發環境的身份驗證需求會由 else 子句中定義的憑證序列來滿足。
重複使用認證實例
盡可能重用認證實例,以提高應用程式的穩定性,並減少發出給 Microsoft Entra ID 的存取令牌要求的數目。 在重複使用認證時,系統會嘗試從由基礎 MSAL 相依性管理的應用程式令牌快取中提取令牌。 如需詳細資訊,請參閱 Azure 身分識別用戶端程式庫中的 令牌快取。
瀏覽器與 Node.js 環境之間的令牌快取行為不同。 在 Node.js 應用程式中,令牌預設會快取於記憶體中,這表示當應用程式重新啟動時,快取的資料會遺失。 在瀏覽器應用程式中,令牌可以保存於瀏覽器記憶體中,localStoragesessionStorage視驗證流程和組態而定。 針對不同的應用程式類型實作認證重複使用策略時,瞭解這些差異非常重要。
這很重要
不重複使用認證的大量應用程式可能會遇到來自 Microsoft Entra ID 的 HTTP 429 節流回應,這可能會導致應用程式中斷。
建議的認證重複使用策略與應用程式架構不同。
若要在 JavaScript 應用程式中實作認證重複使用,請建立單一認證實例,並在所有客戶端物件之間重複使用:
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";
// Create a single credential instance
const credential = process.env.NODE_ENV === 'production'
? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID)
: new DefaultAzureCredential();
// Reuse the credential across different client objects
const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);
const blobServiceClient = new BlobServiceClient(
"https://storageAccountName.blob.core.windows.net",
credential
);
在 Express.js 應用程式中,您可以將認證儲存在應用程式設定中,並在路由處理程式中存取認證:
import express from "express";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";
const app = express();
// Create a single credential instance at app startup
app.locals.credential = process.env.NODE_ENV === 'production'
? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID)
: new DefaultAzureCredential();
// Reuse the credential in route handlers
app.get('/api/secrets/:secretName', async (req, res) => {
const secretClient = new SecretClient(
"https://keyVaultName.vault.azure.net",
req.app.locals.credential
);
try {
const secret = await secretClient.getSecret(req.params.secretName);
res.json({ name: secret.name, value: secret.value });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Add this route to the existing Express app
app.get('/api/blobs/:containerName', async (req, res) => {
const blobServiceClient = new BlobServiceClient(
"https://storageAccountName.blob.core.windows.net",
req.app.locals.credential
);
try {
// Get reference to a container
const containerClient = blobServiceClient.getContainerClient(req.params.containerName);
// List all blobs in the container
const blobs = [];
for await (const blob of containerClient.listBlobsFlat()) {
blobs.push({
name: blob.name,
contentType: blob.properties.contentType,
size: blob.properties.contentLength,
lastModified: blob.properties.lastModified
});
}
res.json({ containerName: req.params.containerName, blobs });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
瞭解何時需要令牌的有效期和快取邏輯
如果您在 Azure SDK 用戶端程式庫之外使用 Azure 身分識別庫憑證,則您需要自行管理應用程式中的 令牌存留期 與快取行為。
refreshAfterTimestamp
AccessToken 上的屬性會向使用者提供關於何時可嘗試重新整理令牌的提示,依賴 Azure Core 程式庫的 Azure SDK 用戶端程式庫將自動使用這個屬性來刷新令牌。 為了直接使用 Azure 身分識別庫的認證以支援令牌快取,底層的 MSAL 快取會在 refreshAfterTimestamp 時間發生時主動自動更新。 此設計可讓客戶端程式碼在每次需要令牌時呼叫 TokenCredential.getToken(),並將重新整理委派給程式庫。
若要在必要時才呼叫 TokenCredential.getToken(),請監控 refreshAfterTimestamp 日期,並在該日期之後主動嘗試刷新令牌。 特定實作由客戶決定。
瞭解受控識別重試策略
適用於 JavaScript 的 Azure 身分識別連結庫可讓您使用 透過受控識別 ManagedIdentityCredential進行驗證。 您使用 ManagedIdentityCredential 的方式會影響套用的重試策略:
- 透過
DefaultAzureCredential使用時,當初始令牌擷取嘗試失敗或在短時間內超時時,不會嘗試重試。 這是最不具彈性的選項,因為它被優化為「快速失敗」以提升開發流程的迴圈效率。 - 任何其他方法,例如
ChainedTokenCredential或ManagedIdentityCredential直接:- 重試之間的時間間隔預設為0.8秒,最多嘗試五次重試。 此選項已針對韌性進行優化,但會在開發的內部迴圈中引入潛在的不受歡迎的延遲。
- 若要變更任何預設重試設定,請在options參數上使用 retryOptions 屬性。 例如,重試最多三次,開始間隔為0.5秒:
import { ManagedIdentityCredential } from "@azure/identity";
const credential = new ManagedIdentityCredential(
process.env.AZURE_CLIENT_ID, // For user-assigned managed identity
{
retryOptions: {
maxRetries: 3, // Maximum number of retry attempts
retryDelayInMs: 500, // Initial delay between retries (in milliseconds)
maxRetryDelayInMs: 5000 // Maximum delay between retries (in milliseconds)
}
}
);
如需自定義受控識別重試原則的詳細資訊,請參閱下列其中一個從 TokenCredentialOptions 延伸的選項: