使用服務主體在本機開發期間向 Azure 服務驗證 JavaScript 應用程式

當您建立雲端應用程式時,開發人員必須在其本機工作站上偵錯及測試應用程式。 當應用程式在本機開發期間於開發人員的工作站上執行時,仍必須向應用程式使用的任何 Azure 服務進行驗證。 本文說明如何設定在本機開發期間要使用的專用應用程式服務主體物件。

此圖顯示本機開發期間 JavaScript 應用程式如何使用開發人員的認證來連線到 Azure,方法是在本機安裝的開發工具取得這些認證。

本機開發專用的應用程式服務主體可讓您遵循應用程式開發期間最低權限的準則。 由於權限的範圍會限定為開發期間應用程式所需的內容,因此應用程式之程式碼無法意外存取要供不同應用程式使用的 Azure 資源。 這個方法也會防止應用程式移至生產環境時發生 Bug,因為應用程式在開發環境中過度許可權。

在 Azure 中註冊應用程式時,會為應用程式設定應用程式服務主體。 為本機開發註冊應用程式時,建議您:

  • 為每個在應用程式上作業的開發人員建立個別的應用程式註冊。 此方法會建立個別的應用程式服務主體,讓每個開發人員在本機開發期間使用,並避免開發人員需要共用單一應用程式服務主體的認證。
  • 為每個應用程式建立個別的應用程式註冊。 這麼做會限制應用程式的權限,使之僅具備所需的權限。

在本機開發期間,會使用應用程式服務主體的身分識別來設定環境變數。 適用於 JavaScript 的 Azure SDK 會讀取這些環境變數,並使用這項資訊向所需的 Azure 資源驗證應用程式。

1:在 Azure 中註冊應用程式

系統會用於 Azure 註冊的應用程式建立應用程式服務主體物件。 您可以使用 Azure 入口網站 或 Azure CLI 來建立服務主體。

登入 Azure 入口網站並遵循下列步驟。

指示 Screenshot
在 Azure 入口網站中:
  1. 在 Azure 入口網站頂端的搜尋列中輸入應用程式註冊
  2. 在搜尋列下方出現的功能表上的 服務 標題下,選取標有 應用程式註冊 的項目。
顯示如何使用 Azure 入口網站 頂端搜尋列來尋找並流覽至 應用程式註冊 頁面的螢幕快照。
在 [應用程式註冊] 頁面上,選取 [+ 新增註冊] 顯示 [應用程式註冊] 頁面中 [新增註冊] 按鈕位置的螢幕快照。
在 [註冊應用程式] 頁面中,如下所示填妥表單。
  1. 名稱 → 輸入 Azure 中應用程式註冊的名稱。 建議在此名稱中納入應用程式的名稱、應用程式註冊的使用者,以及 'dev' 之類的識別碼,表示此應用程式註冊係用於本機開發。
  2. 支援的帳戶類型僅限此組織目錄中的帳戶
選取 [註冊] 來註冊您的應用程式,並建立應用程式服務主體。
此螢幕快照顯示如何填寫 [註冊應用程式] 頁面,方法是提供應用程式的名稱,並將支援的帳戶類型指定為僅限此組織目錄中的帳戶。
在您應用程式的 [應用程式註冊] 頁面中:
  1. 應用程式 (用戶端) 識別碼 →這是應用程式在本機開發期間用來存取 Azure 的應用程式識別碼。 將此值複製到文本編輯器中的暫存位置,因為您將在未來的步驟中用到此值。
  2. 目錄 (租用戶) 識別碼 → 此值也會於應用程式向 Azure 驗證時派上用場。 請將此值複製到文字編輯器內的暫存位置,後續步驟同樣還會用到。
  3. 用戶端認證 → 您必須為應用程式設定用戶端認證,之後應用程式才能向 Azure 驗證並使用 Azure 服務。 請選取 [新增憑證或祕密],將憑證新增至您的應用程式。
應用程式註冊完成後的螢幕快照,其中包含應用程式標識碼、租使用者標識碼的位置。
在 [憑證及祕密] 頁面中,選取 [+ 新增用戶端密碼] 此螢幕快照顯示用來在憑證和秘密頁面上建立新用戶端密碼的連結位置。
[新增用戶端密碼] 對話方塊會在頁面右側彈出。 此對話方塊會顯示:
  1. 說明 → 輸入 Current 的值。
  2. 到期 → 選取 24 個月 的值。
選取 [新增] 新增祕密。
此螢幕快照顯示應用程式註冊程式為應用程式服務主體建立新增用戶端密碼的頁面。
在 [ 憑證與秘密] 頁面上,您會看到客戶端密碼的值。

將此值複製到文本編輯器中的暫存位置,因為您將在未來的步驟中用到此值。

重要:這是您唯一會看到此值的時間。 離開或重新整理此頁面之後,您將無法再次看到此值。 您可以新增更多客戶端密碼,而不會使此客戶端密碼失效,但您不會再次看到此值。
顯示具有所產生客戶端密碼之頁面的螢幕快照。

2 - 建立 Microsoft Entra 安全組以進行本機開發

由於通常有多個開發人員在應用程式上工作,因此建議建立 Microsoft Entra 群組來封裝應用程式在本機開發中所需的角色(許可權),而不是將角色指派給個別服務主體物件。 這具有以下優點。

  • 由於角色是在群組層級指派,因此指派給每位開發人員的角色都能保證相同。
  • 如果應用程式需要新的角色,它只需要新增至應用程式的 Microsoft Entra 群組。
  • 如有新開發人員加入小組,則系統會為其建立新的應用程式服務主體並新增至群組,確定開發人員具備處理應用程式的適當權限。
指示 Screenshot
在頁面頂端的搜尋方塊中輸入 Microsoft Entra ID,然後從服務底下選取 Microsoft Entra ID,以流覽至 Azure 入口網站 中的 Microsoft Entra 標識符頁面。 顯示如何使用 Azure 入口網站 頂端搜尋列來搜尋並流覽至 Microsoft Entra ID 頁面的螢幕快照。
在 [ Microsoft Entra 標識符 ] 頁面上,從左側功能表中選取 [群組 ]。 顯示 Microsoft Entra ID 預設目錄頁面左側選單中 [群組] 選單項位置的螢幕快照。
在 [所有群組] 頁面中,選取 [新增群組] 顯示 [所有群組] 頁面中 [新增群組] 按鈕位置的螢幕快照。
在 [新增群組] 頁面進行下列設定:
  1. [群組類型] → [安全性]
  2. [群組名稱] → 安全性群組的名稱,通常從應用程式名稱建立。 在群組名稱中包含 local-dev 這樣的字串也很有幫助,能夠指出群組的用途。
  3. [群組描述] → 群組用途的描述。
  4. 選取 [成員] 下方的 [未選取任何成員] 連結,為群組新增成員。
顯示如何為應用程式建立新 Microsoft Entra 群組的螢幕快照。
在 [新增成員] 對話方塊進行下列設定:
  1. 使用搜尋方塊篩選清單中的主體名稱列表。
  2. 為此應用程式選取本機開發的應用程式服務主體。 選取物件後,物件會以灰色顯示,並移至對話方塊底部的 選取的項目 清單。
  3. 完成後,選取 [選取] 按鈕。
[新增成員] 對話框的螢幕快照,其中顯示如何選取要包含在群組中的應用程式服務主體。
回到 [新增群組] 頁面,選取 [建立] 以建立群組。

群組隨即建立,而您會回到 [所有群組] 頁面。 群組最多可能需 30 秒才會顯示,且礙於 Azure 入口網站中的快取,您可能必須重新整理頁面才能看見。
[新增群組] 頁面的螢幕快照,其中顯示如何選取 [建立] 按鈕來完成程式。

3:為應用程式指派角色

接著,您必須決定應用程式針對哪些資源需要哪些角色 (權限),並將這些角色指派給應用程式。 在此範例中,角色會指派給步驟 2 中建立的 Microsoft Entra 群組。 角色可在資源、資源群組或訂閱範圍內獲派其他角色。 此範例示範如何在資源群組範圍中指派角色,因為大部分的應用程式都會將其所有 Azure 資源群組組成單一資源群組。

指示 Screenshot
用 Azure 入口網站頂端的搜尋方塊,搜尋資源群組的名稱,藉此找出應用程式的資源群組。

選取對話方塊中 資源群組 標題下方的資源群組名稱,瀏覽至您的資源群組。
此螢幕快照顯示如何使用 Azure 入口網站 中的頂端搜尋方塊來尋找並流覽至您要指派角色的資源群組(許可權)。
在資源群組分頁中,從左側功能表選取 存取控制 (IAM) 資源群組頁面的螢幕快照,其中顯示訪問控制 (IAM) 功能表項的位置。
存取控制 (IAM) 分頁上:
  1. 選取 [角色指派] 索引標籤。
  2. 從頂端功能表選取 [+ 新增],然後從產生的下拉功能表中選取 [新增角色指派]
此螢幕快照顯示如何流覽至 [角色指派] 索引標籤,以及用來將角色指派新增至資源群組的按鈕位置。
新增角色指派 分頁列出所有可指派至資源群組之角色的清單。
  1. 請善用搜尋方塊,將清單篩選為更易於管理的大小。 此範例顯示如何針對儲存體 Blob 角色進行篩選。
  2. 選取您要指派的角色。
    選取 [下一步] 前往下一個畫面。
顯示如何篩選和選取要新增至資源群組的角色指派的螢幕快照。
下一個 新增角色指派 分頁能讓您指定要指派角色的使用者。
  1. 選取 [存取權指派對象為] 下的 [使用者、群組或服務主體]
  2. 選取 [成員] 下的 [+ 選取成員]
對話框會在 Azure 入口網站 右側開啟。
此螢幕快照顯示要選取將角色指派給 Microsoft Entra 群組的單選按鈕,以及用來選取要指派角色之群組的連結。
在 [選取成員] 對話方塊進行下列設定:
  1. [選取] 文字輸入框可用來篩選訂閱中的使用者及群組清單。 如有需要,請輸入您為應用程式建立之本機開發 Microsoft Entra 群組的前幾個字元。
  2. 選取與您應用程式相關聯的本機開發 Microsoft Entra 群組。
選取對話方塊底部的 [選取] 來繼續。
螢幕快照,顯示如何在 [選取成員] 對話框中篩選及選取應用程式的 Microsoft Entra 群組。
Microsoft Entra 群組會在 [ 新增角色指派 ] 畫面上顯示為已選取。

選取 [檢閱 + 指派] 移至最終分頁,然後再次選取 [檢閱 + 指派] 完成此流程。
此螢幕快照顯示已完成的 [新增角色指派] 頁面,以及用來完成程式之 [檢閱 + 指派] 按鈕的位置。

4 - 設定本機開發環境變數

物件 DefaultAzureCredential 會在運行時間的一組環境變數中尋找服務主體資訊。 由於大部分開發人員都處理多個應用程式,因此建議使用 dotenv 之類的套件,從.env應用程式目錄中儲存的檔案在開發期間存取環境。 這會限定用來向 Azure 驗證應用程式的環境變數,讓它們只能供此應用程式使用。

檔案 .env 永遠不會簽入原始檔控制,因為它包含 Azure 的應用程式秘密密鑰。 JavaScript 的標準 .gitignore 檔案會自動從簽入中排除 .env 檔案。

若要使用 dotenv 套件,請先在應用程式中安裝套件。

npm install dotenv

然後,在應用程式根目錄中建立 .env 檔案。 使用從應用程式註冊程式取得的值來設定環境變數值,如下所示:

  • AZURE_CLIENT_ID → 應用程式識別碼的值。
  • AZURE_TENANT_ID → 租用戶識別碼的值。
  • AZURE_CLIENT_SECRET → 為應用程式產生的密碼/認證。
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz

最後,在應用程式的啟動程式代碼中,使用連結 dotenv 庫從啟動時從 .env 檔案讀取環境變數。

import 'dotenv/config'

5:在應用程式中實作 DefaultAzureCredential

若要向 Azure 驗證 Azure SDK 用戶端物件,您的應用程式應該使用 DefaultAzureCredential 套件中的 @azure/identity 類別。 在此案例中, DefaultAzureCredential 會偵測環境變數 AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET 已設定並讀取這些變數,以取得要連線到 Azure 的應用程式服務主體資訊。

首先,將 @azure/身分 識別套件新增至您的應用程式。

npm install @azure/identity

接下來,針對在應用程式中建立 Azure SDK 用戶端物件的任何 JavaScript 程式代碼,您會想要:

  1. 從模組匯入 DefaultAzureCredential@azure/identity 類別。
  2. 建立 DefaultAzureCredential 物件。
  3. DefaultAzureCredential 對象傳遞至 Azure SDK 用戶端物件建構函式。

下列程式碼區段示範其中一種範例。

// Azure authentication dependency
import { DefaultAzureCredential } from '@azure/identity';

// Azure resource management dependency
import { SubscriptionClient } from "@azure/arm-subscriptions";

// Acquire credential
const tokenCredential = new DefaultAzureCredential();

async function listSubscriptions() {
  try {

    // use credential to authenticate with Azure SDKs
    const client = new SubscriptionClient(tokenCredential);

    // get details of each subscription
    for await (const item of client.subscriptions.list()) {
      const subscriptionDetails = await client.subscriptions.get(
        item.subscriptionId
      );
      /* 
        Each item looks like:
      
        {
          id: '/subscriptions/123456',
          subscriptionId: '123456',
          displayName: 'YOUR-SUBSCRIPTION-NAME',
          state: 'Enabled',
          subscriptionPolicies: {
            locationPlacementId: 'Internal_2014-09-01',
            quotaId: 'Internal_2014-09-01',
            spendingLimit: 'Off'
          },
          authorizationSource: 'RoleBased'
        },
    */
      console.log(subscriptionDetails);
    }
  } catch (err) {
    console.error(JSON.stringify(err));
  }
}

listSubscriptions()
  .then(() => {
    console.log("done");
  })
  .catch((ex) => {
    console.log(ex);
  });

DefaultAzureCredential 會自動偵測為應用程式設定的驗證機制,並取得向 Azure 驗證應用程式所需的令牌。 如果應用程式使用多個SDK用戶端,則相同的認證物件可以與每個SDK客戶端物件搭配使用。