練習 - 實作多租用戶資料

已完成

此練習會引領完成下列程序:

  • 在伺服器部署模型中安裝適用於 PostgreSQL 的 Azure 資料庫。
  • 使用範例清查資料建立資料庫。
  • 將伺服器與 Microsoft Entra ID 整合。
  • 實作簡單的 Node.js 式應用程式,透過依賴 Microsoft Entra 驗證以查詢資料庫。

注意

此練習透過模擬適用於 PostgreSQL 的 Azure 資料庫超大規模部署模型的多組織用戶管理功能,示範提供多租用戶支援的簡化方式。 它也提供簡化的方法,藉由依賴 Microsoft Entra B2B 功能,在多租使用者案例中實作 Microsoft Entra 驗證。 Microsoft Entra ID 直接支援多租用戶應用程式,但其詳細涵蓋範圍超出本課程模組的範圍。

在本練習中,您將會:

  • 在適用於 PostgreSQL 的 Azure 資料庫中建立執行個體。
  • 連線至適用於 PostgreSQL 的 Azure 資料庫伺服器。
  • 建立資料庫和範例資料表。
  • 將適用於 PostgreSQL 的 Azure 資料庫伺服器與 Microsoft Entra ID 整合。
  • 使用 Microsoft Entra ID 註冊應用程式。
  • 實作簡單的 Microsoft Entra 整合式 Node.js 應用程式。
  • 驗證 Node.js 型應用程式的功能。

必要條件

若要執行此練習,您將需要:

  • Azure 訂用帳戶。
  • Microsoft 帳戶或 Microsoft Entra 帳戶,這在與 Azure 訂用帳戶相關聯的 Microsoft Entra 租用戶中具有全域管理員角色,而在 Azure 訂用帳戶中具有擁有者或參與者角色。
  • 完成此課程模組的第一個練習。

在適用於 PostgreSQL 伺服器的 Azure 資料庫中建立執行個體

您將從建立適用於 PostgreSQL 伺服器的 Azure 資料庫伺服器的執行個體開始:

  1. 如有需要,請啟動網頁瀏覽器,巡覽至 Azure 入口網站並登入,以存取您將在本課程模組中使用的 Azure 訂閱。

  2. 使用 Azure 入口網站頁面開頭的 [搜尋資源、服務及文件] 文字輸入框來搜尋適用於 PostgreSQL 的 Azure 資料庫,然後在結果清單的 [服務] 區段中選取 [適用於 PostgreSQL 的 Azure 資料庫]。

  3. 在 [適用於 PostgreSQL 伺服器的 Azure 資料庫] 窗格上,選取 [+ 建立]。

  4. 在 [適用於 PostgreSQL 的 Azure 資料庫] 圖格的 [選取適用於 PostgreSQL 的 Azure 資料庫部署選項] 窗格上,針對 [資源類型] 選取 [單一伺服器]。

  5. 選取建立

  6. 在 [單一伺服器] 窗格的 [基本] 索引標籤上,設定下列設定,然後選取 [檢閱 + 建立],並保留所有其他設定的預設值:

    設定 組態
    訂用帳戶 選取您將在本課程模組中使用的 Azure 訂用帳戶名稱。
    資源群組 建立新的資源群組,並命名為 postgresql-db-RG
    伺服器名稱 輸入由小寫字母、數字或破折號組成的唯一名稱,並以字母開頭。
    資料來源 選取 [無]。
    位置 選取最接近您實驗室環境所在位置的 Azure 區域,以便在其中建立適用於 PostgreSQL 的 Azure 資料庫執行個體。
    版本 選取 [11]
    計算 + 儲存體 選取 [設定伺服器] 連結。 在 [設定] 刀鋒視窗上選取 [基本],將 [虛擬核心] 值設定為 1,並將 [儲存體] 設定為 5 GB,然後選取 [確定]
    管理員使用者名稱 輸入學生
    密碼 輸入 Pa55w0rd1234

    Screenshot of the Basics tab of the server blade in the Azure portal.

  7. 在 [單一伺服器] 窗格的 [檢閱 + 建立] 索引標籤上,選取 [建立]

  8. 等候佈建完成。 這大約需要五分鐘的時間。

    注意

    布建程序會自動在目標伺服器內建立名為 postgres 的資料庫。

連線至「適用於 PostgreSQL 的 Azure 資料庫」伺服器

佈建適用於 PostgreSQL 的 Azure 資料庫伺服器之後,您就可以使用 psql 工具與其連線。

  1. 在 [Microsoft.PostgreSQLServer.createPostgreSqlServer 概觀] 窗格中,選取 [前往資源].

  2. 在 [部署] 窗格上,於垂直功能表的 [設定] 區段中選取 [連線安全性]。

  3. 在 [連線安全性] 刀鋒視窗上,將 [允許存取 Azure 服務] 設定為 [是],選取 [+ 新增用戶端 IP],將 [強制執行 SSL 連線] 設定為 [停用],然後選取 [儲存]

    注意

    這些設定可讓您從電腦和在 Azure 中執行的應用程式連線到資料庫。

    注意

    停用實施 SSL 是為了簡化後續的練習。 一般情況下,請讓此設定保持啟用狀態。

  4. 在顯示 Azure 入口網站與 [部署] 窗格的瀏覽器視窗中,選取垂直功能表中的 [概觀]。

  5. 在 [基本資訊] 區段中,找到 [伺服器名稱] 和 [管理員使用者名稱] 標籤旁的項目,並記錄下這兩個項目的值。

    注意

    請注意,使用者名稱中會包含 @ 符號,後面接著您在上一個工作中所指定的伺服器名稱。

  6. 在顯示 Azure 入口網站與 [適用於 PostgreSQL 單一伺服器的 Azure 資料庫] 窗格的瀏覽器視窗中,於垂直功能表的 [設定] 區段中選取 [連接字串]。

  7. 在連接字串清單中,複製 psql 連接字串的值並加以記錄,以便稍後在此練習中使用。

    注意

    連接字串具有下列語法,其中 <server_name> 預留位置代表您先前在此工作中所識別的伺服器名稱:

    psql "host=<server_name>.postgres.database.azure.com port=5432 dbname={your_database} user=student@<server_name> password={your_password} sslmode=require"
    
  8. 在 Azure 入口網站中,開啟 [Cloud Shell] 的 Bash 工作階段,方法是在搜尋文字方塊旁的工具列中選取其圖示。

  9. 在 [Cloud Shell] 窗格上的 Bash 工作階段中,貼上剪貼簿中的 psql 連接字串值,加以修改使其符合下列命令,然後執行以連線到適用於 PostgreSQL 之 Azure 資料庫新部署伺服器執行個體上裝載的 postgres 資料庫。 <server_name> 預留位置的值已包含在您從剪貼簿貼上的連接字串中:

    psql "host=<server_name>.postgres.database.azure.com port=5432 dbname=postgres user=student@<server_name>.postgres.database.azure.com password=Pa55w0rd1234 sslmode=require"
    

    注意

    當成功連線時,會看到 postgres=> 提示字元。

建立資料庫和範例資料表

  1. 在 [Cloud Shell] 窗格中,從 postgres=> 提示執行下列命令,以建立名為 cnamtinventory 的新資料庫:

    CREATE DATABASE cnamtinventory;
    
  2. 執行下列命令將連線對象切換為新建立的資料庫:

    \c cnamtinventory
    
  3. 執行下列命令,以建立租用戶資料表:

    CREATE TABLE tenants (
      id bigserial PRIMARY KEY,
      name text NOT NULL,
      created_at TIMESTAMP DEFAULT NOW()::date,
      updated_at TIMESTAMP DEFAULT NOW()::date
    );
    
  4. 執行下列命令,以建立清查資料表:

    CREATE TABLE inventory (
    id bigserial, 
    tenant_id bigint REFERENCES tenants (id),
    name VARCHAR(50),
    quantity INTEGER,
        date DATE NOT NULL DEFAULT NOW()::date,
        created_at TIMESTAMP DEFAULT NOW()::date,
        updated_at TIMESTAMP DEFAULT NOW()::date,
        PRIMARY KEY (tenant_id, id, date)
    ) PARTITION BY RANGE (date);
    
    CREATE TABLE inventory_default PARTITION OF inventory DEFAULT;
    

    注意

    資料會根據日期資料行的值進行分割。

  5. 執行下列命令來確認系統是否已成功建立資料表:

    \dt
    
  6. 執行下列命令,將範例資料載入租用戶資料表:

    INSERT INTO tenants (id, name) VALUES (1, 'adatum');
    INSERT INTO tenants (id, name) VALUES (2, 'contoso');
    
  7. 執行下列命令,將範例資料載入清查資料表:

    INSERT INTO inventory (id, tenant_id, name, quantity) VALUES (1, 1, 'yogurt', 200);
    INSERT INTO inventory (id, tenant_id, name, quantity) VALUES (2, 1, 'milk', 100);
    INSERT INTO inventory (id, tenant_id, name, quantity) VALUES (1, 2, 'yogurt', 20);
    INSERT INTO inventory (id, tenant_id, name, quantity) VALUES (2, 2, 'milk', 10);
    
  8. 執行下列命令,確認清查資料表包含所插入的資料:

    SELECT * FROM inventory;
    
  9. 關閉 [Cloud Shell] 窗格。

將適用於 PostgreSQL 的 Azure 資料庫伺服器與 Microsoft Entra ID 整合

若要將適用於 PostgreSQL 的 Azure 資料庫伺服器執行個體與 Microsoft Entra ID 整合,您必須提供 Microsoft Entra 使用者帳戶作為伺服器的指定 Active Directory 管理員。 基於此目的,您將使用在上一個工作中建立的 adatumadmin1 使用者帳戶。 您必須使用該使用者帳戶登入伺服器。 屆時,您將能夠建立以 Microsoft Entra ID 為基礎的資料庫使用者,並為其指派資料庫角色。 您將針對在上一個練習中建立的 adatumuser1adatumgroup1contosouser1 Microsoft Entra 物件使用。

  1. 在顯示 Azure 入口網站與 [適用於 PostgreSQL 的 Azure 資料庫伺服器] 刀鋒視窗的瀏覽器視窗中,於垂直功能表的 [設定] 區段中選取 [Active Directory 管理員],然後在工具列中選取 [設定管理員]

  2. 在 [Active Directory 管理員] 刀鋒視窗的 Microsoft Entra 使用者帳戶清單中,選取您在上一個練習中建立的 adatumadmin1 使用者帳戶,然後依序選取 [選取] 和 [儲存]

  3. 以無痕/InPrivate 模式開啟另一個網頁瀏覽器視窗,巡覽至 Azure 入口網站,並使用您在上一個練習中建立的 adatumadmin1 使用者帳戶 (密碼為 Pa55w.rd1234) 登入。

  4. 在 Azure 入口網站中開啟 [Cloud Shell],方法是在搜尋文字方塊旁的工具列中選取其圖示。

  5. 當系統提示選取 [Bash] 或 [PowerShell] 時,請選取 [Bash],然後在看到 [您未掛接任何儲存體] 訊息時,選取 [建立儲存體]

  6. 在 [Cloud Shell] 窗格的 Bash 工作階段中,執行下列命令以擷取並顯示存取適用於 PostgreSQL 的 Azure 資料庫所需的 Microsoft Entra 存取權杖:

    FULL_TOKEN=$(az account get-access-token --resource-type oss-rdbms)
    echo $FULL_TOKEN
    

    注意

    此命令會產生包含 Base 64 編碼權杖的輸出,以識別適用於 PostgreSQL 之 Azure 資料庫資源的已驗證使用者。

    輸出會使用下列格式:

    {
      "accessToken": "eyJ0eXAiOiJKV1QiLDJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL29zc3JkYm1zLWFhZC5kYXRhYmFzZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2E2MTM5NTE0LTQxYTUtNDEyMy05ODFhLWVlN2JiOWU2YTNiNC8iLCJpYXQiOjE2MjE2MTc0NjUsIm5iZiI6MTYyMTYxNzQ2NSwiZXhwIjoxNjIxNjIxMzY0LCJhY3IiOiIxIiwiYWlvIjoiQVRRQXkvOFRBQUFBU1I5cXdVcm9KVVpmWEJabHY1NzRUenpmeGZFUlo1SXNDV3Z1aDVEOVBGWnZsL09SYWYzTGg3Zmx4NEFVaFpkVSIsImFtciI6WyJwd2QiXSwiYXBwaWQiOiJiNjc3YzI5MC1jZjRiLTRhOGUtYTYwZS05MWJhNjUwYTRhYmUiLCJhcHBpZGFjciI6IjIiLCJpcGFkZHIiOiIxNDIuMTA1LjQ4LjUxIiwibmFtZSI6ImFkYXR1bWFkbWluMSIsIm9pZCI6Ijc2ZTdmYWI5LTZiOTItNGQzZi1hOGI5LWY1NWNhNDQyYzZiMSIsInB1aWQiOiIxMDAzMjAwMTQ0RTNDMDBBIiwicmgiOiIwLkFYd0FGSlVUcHFWQkkwR1lHdTU3dWVhanRKRENkN1pMejQ1S3BnNlJ1bVVLU3I1OEFNay4iLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJvNmhNMWlHXzM3MExaQk92UlpUQjBYeEdjSmpaOUVmN21lc1N2RkJYY3FFIiwidGlkIjoiYTYxMzk1MTQtNDFhNS00MTIzLTk4MWEtZWU3YmI5ZTZhM2I0IiwidW5pcXVlX25hbWUiOiJhZGF0dW1hZG1pbjFAbGl2ZWlkMjE3b3V0bG9vay5vbm1pY3Jvc29mdC5jb20iLCJ1cG4iOiJhZGF0dW1hZG1pbjFAbGl2ZWlkMjE3b3V0bG9vay5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJJdE81VndoU2lVV0o0UUZNQ04xQUFRIiwidmVyIjoiMS4wIn0.fFV3s2OjpVU52_SA8-atIDdkLN4onLgPmYrxa5eNCbuF0VbVOA5a9Ifv66H5a__6lMiLoV8n9EgTV4CpsLmvn6JFjAD9aHyEBkS2_iL_Rx-KCmlc7Vr6UHezrlrA3skf8oq3yb2Zqy_A3_kOrsnFgX8NP5uWoMmTzjWGTw3rOfjERJ7PowQC60nzlF1uCRDKIWw62SW4xiDQj23DSLDbkfUiG_Z9Swbw4DuMPTPeUVwz9AWhmg8lrqt5oawhKB-OMcpuwSf1-rE1cf2w54uthU6764DBEf5MVt8K95AKW0rey888znrIGKT-6yFenYUZZjL1aJ-jz8OIyNjuQK73XQ",
      "expiresOn": "2021-05-21 18:22:44.000000",
      "subscription": "d15bacf3-b17b-4ad5-a913-5fb904bd2f71",
      "tenant": "a6239514-41a5-4123-981a-ee7bb9e6a3b4",
      "tokenType": "Bearer"
    }
    
  7. 執行下列命令,將 PGPASSWORD 變數的值設定為在上一個步驟中所執行命令輸出中的存取權杖值:

    export PGPASSWORD=$(echo $FULL_TOKEN | jq -r '.accessToken')
    
  8. 執行下列命令,使用 psql 工具並藉由使用 Microsoft Entra 驗證 (以先前在本練習中所識別的伺服器名稱取代 <server_name> 預留位置) 連線到 cnamtinventory 資料庫:

    DOMAIN_NAME=$(az rest --method GET --url 'https://management.azure.com/tenants?api-version=2020-01-01' --query "value[0].defaultDomain" -o tsv)
    psql "host=<server_name>.postgres.database.azure.com user=adatumadmin1@$DOMAIN_NAME@<server_name> dbname=cnamtinventory sslmode=require"
    

    注意

    當成功連線時,應該會看到 cnamtinventory=> 提示字元。

  9. cnamtinventory=> 提示字元執行下列命令,以建立對應至在上一個練習中所建立 adatumgroup1 Microsoft Entra 群組的資料庫角色:

    CREATE ROLE "adatumgroup1" WITH LOGIN IN ROLE azure_ad_user;
    
  10. 執行下列命令,確認已成功建立角色:

    SELECT rolname FROM pg_roles;
    
  11. 執行下列命令,將 [清查] 資料表上的 SELECT 權限授與您在上一個練習中建立的 adatumgroup1

    GRANT SELECT ON inventory TO adatumgroup1;
    
  12. adatumadmin1 使用者帳戶登出,然後關閉無痕/InPrivate 模式的網頁瀏覽器視窗。

練習 - 使用 Microsoft Entra ID 註冊應用程式

若要實作範例 Node.js 型應用程式以使用 Microsoft Entra 驗證存取適用於 PostgreSQL 的 Azure 資料庫,您必須建立 Microsoft Entra 應用程式物件和對應的安全性主體。 這可讓 Node.js 型應用程式在存取資料庫物件時模擬 Microsoft Entra 使用者。

  1. 在 Azure 入口網站中,使用 [搜尋資源、服務和文件] 文字輸入框,搜尋 Microsoft Entra ID,然後在結果清單中選取 [Microsoft Entra ID]

  2. 在 [Microsoft Entra] 刀鋒視窗上,於垂直功能表的 [管理] 區段中選取 [應用程式註冊]

  3. 在 [應用程式註冊] 刀鋒視窗上,選取 [+ 新增註冊]

  4. 在 [註冊應用程式] 刀鋒視窗的 [名稱] 文字方塊中,輸入 cna-app。 在 [支援的帳戶類型] 區段中,確定已選取 [僅此組織目錄中的帳戶 (僅預設目錄 - 單一租用戶)] 選項。 在 [重新導向 URI (選用)] 區段中,將 [Web] 項目設定為 http://localhost:8080/redirect,然後選取 [註冊]

    Screenshot of the Register an application blade in the Azure portal.

    注意

    您可以選擇為已註冊的 Microsoft Entra 應用程式設定多租用戶支援。 不過,此方法的詳細涵蓋範圍不在本課程模組的討論範圍內。

    注意

    部署應用程式之後,您必須修改 [重新導向 URI (選用)] 值以反映其實際 URL。

  5. 在 [cna-app] 刀鋒視窗上,檢閱產生的設定,並記錄 [應用程式 (用戶端) 識別碼] 和 [目錄 (租用戶) 識別碼] 屬性的值。

    Screenshot of the cna-app blade in the Azure portal.

  6. 在 [cna-app] 刀鋒視窗的 [管理] 區段中選取 [憑證及祕密],然後選取 [+ 新增用戶端祕密]

  7. 在 [+ 新增用戶端祕密] 刀鋒視窗的 [描述] 文字方塊中,輸入 cna-secret-0。 將 [到期] 下拉式清單項目保留為預設值,然後選取 [新增]

    Screenshot of the Add a client secret blade in the Azure portal.

  8. 回到 can-app |[憑證與秘密] 刀鋒視窗,複製新產生的秘密值。

    注意

    在離開此刀鋒視窗之前,請務必複製祕密值,因為之後您將無法再擷取此值。 如果發生這種情況,請建立其他祕密。

    Screenshot of the value of the client secret on the cna-app Certificates & secrets blade in the Azure portal.

  9. can-app 上 |[憑證與秘密] 刀鋒視窗,在垂直功能表中的 [管理 ] 區段中,選取 [ API 許可權]。

    Screenshot of the cna-app API permissions blade in the Azure portal.

  10. 在 [cna-app | API 權限] 刀鋒視窗上選取 [+ 新增權限],在 [要求 API 權限] 刀鋒視窗上選取 [我的組織使用的 API] 索引標籤,在搜尋文字方塊中輸入 Azure OSSRDBMS Database,然後在結果清單中選取 [Azure OSSRDBMS Database]

    Screenshot of the Request API permissions blade in the Azure portal.

  11. 在 [要求 API 權限] 窗格上,依序選取 [委派的權限]、[user_impersonation] 核取方塊和 [新增權限]。

    Screenshot of the Request API permissions blade in the Azure portal, with the Delegated permissions option selected.

  12. 回到 [cna-app | API 權限] 刀鋒視窗,選取 [授與預設目錄的管理員同意],並在出現確認提示時選取 [是]

    Screenshot of the cna-app API permissions blade in the Azure portal, with the prompt to confirm granting of the admin consent.

  13. 在 [cna-app | API 權限] 刀鋒視窗上,確認已授與權限。

    Screenshot of the cna-app API permissions blade in the Azure portal, with the consent and permissions granted.

實作簡單的 Microsoft Entra 整合式 Node.js 應用程式

在 Microsoft Entra 租用戶中註冊應用程式之後,您現在可以繼續進行其實作。

  1. 在 Azure 入口網站中,於 [Cloud Shell] 內啟動 Bash 工作階段,方法是在搜尋文字方塊旁的工具列中選取其圖示。

  2. 在 [Cloud Shell] 窗格的 Bash 工作階段內,執行下列命令以在新目錄中初始化 Node.js 專案:

    mkdir -p cna-aadexpress && cd cna-aadexpress
    npm init -y
    
  3. 執行下列命令,以將必要套件新增至專案的相依性:

    npm install express
    npm install pg
    npm install @azure/msal-node
    
  4. 執行下列命令,以在專案的根目錄中建立名為 index.js 的檔案:

    touch ./index.js
    
  5. 使用 nano 編輯器開啟 index.js 檔案,並新增下列內容。 您稍後會在此單元中建立應用程式名稱,以取代預留位置 <webapp_name>。 以稍早在此練習中記錄的實際值取代 <client_id><tenant_id><client_secret><server_name> (不含 .postgres.database.azure.com 尾碼):

    注意

    預留位置 <client_id><tenant_id> 會分別對應至此練習中稍早所參考的 [應用程式 (用戶端) 識別碼] 和 [目錄 (租用戶) 識別碼] 屬性。

    // Import dependencies
    const express = require("express");
    const msal = require('@azure/msal-node');
    const pg = require('pg');
    const port = process.env.PORT || 8080
    // Initialize express
    const app = express();
    app.use(express.json());
    app.listen(port, () => console.log(`Sample app is listening on port ${port}!`))
    
    // Authentication parameters
    const config = {
    auth: {
            clientId: "<client_id>",
            authority: "https://login.microsoftonline.com/<tenant_id>",
            clientSecret: "<client_secret>"
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
            console.log(message);
            },
        piiLoggingEnabled: false,
        logLevel: msal.LogLevel.Verbose,
        }
        }
    };
    
    var outputrows = ""
    
    // Initialize MSAL Node object using authentication parameters
    const cca = new msal.ConfidentialClientApplication(config);
    
    app.get('/auth', (req, res) => {
    
    redirectUri = req.hostname.toLowerCase()=="localhost" ? "http://localhost:8080/redirect" : "https://<webapp_name>.azurewebsites.net/redirect";
    
    // Construct a request object for auth code
    const authCodeUrlParameters = {
        scopes: ["https://ossrdbms-aad.database.windows.net/user_impersonation"],
        redirectUri: redirectUri,
    };
    
    // Request auth code, then redirect
    cca.getAuthCodeUrl(authCodeUrlParameters)
        .then((response) => {
            res.redirect(response);
        }).catch((error) => res.send(error));
    });
    
    app.get('/redirect', (req, res) => {
    redirectUri = req.hostname.toLowerCase()=="localhost" ? "http://localhost:8080/redirect" : "https://<webapp_name>.azurewebsites.net/redirect";
    
    // Use the auth code in redirect request to construct a token request object
    const tokenRequest = {
        code: req.query.code,
        scopes: ["https://ossrdbms-aad.database.windows.net/user_impersonation"],
        redirectUri: redirectUri,
    };
    
    // Exchange the auth code for tokens
    cca.acquireTokenByCode(tokenRequest)
    .then((response) => {
        //res.send(response);
    
        var username = 'adatumgroup1';
        var databasename = 'cnamtinventory';
        var servername = '<server_name>';
        var tablename = 'inventory';
    
        process.env.PGPASSWORD = response.accessToken;
        const connectionString =
            `postgres://${username}@${servername}@${servername}.postgres.database.azure.com:5432/${databasename}?ssl=true`;
    
        res.write(connectionString + "\n\n");
        res.write(response.accessToken + "\n\n");
    
        const client = new pg.Client(connectionString);
        client.connect(err => {
            if (err) throw err;
            else {
                queryDatabase(response.account.name);
            }
        });
    
        function queryDatabase(tenant_id) {
            console.log(`Running query to PostgreSQL server: ${servername}`);
            switch (tenant_id) {
                case "adatumuser1":
                    id = "1";
                    break;
                case "contosouser1":
                    id = "2";
                    break;
            }
            const query = `SELECT * FROM ${tablename} WHERE tenant_id = ${id};`;
            client.query(query)
            .then(qresponse => {
                const rows = qresponse.rows;
                rows.map(row => {
                    var singlerow = `${JSON.stringify(row)}`;
                    console.log(singlerow);
                    outputrows += singlerow + "\n";
                });
                res.write(outputrows);
                res.end();
                process.exit();
            })
            .catch(err => {
                 console.log(err);
            });
        }
      }).catch((error) => res.write(error));
    });
    

    注意

    多租用戶 Microsoft Entra 註冊的應用程式會使用一般授權單位 URL authority: "https://login.microsoftonline.com/common",但在案例中,必須使用包含您租用戶識別碼的單一租用戶 URL。

    注意

    請記住,在部署應用程式之後,您必須使用實際的重新導向 URL 來取代 [重新導向 URL] 的值。

  6. 使用 nano 編輯器來編輯專案根目錄中的 package.json 檔案,並將其取代為下列內容:

    {
      "name": "node-express",
      "version": "1.0.0",
      "description": "Node.js express sample",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "@azure/msal-node": "^1.1.0",
        "body-parser": "^1.19.0",
        "express": "^4.17.1",
        "http": "0.0.0",
        "morgan": "^1.10.0",
        "pg": "^8.6.0"
      }
    }
    

驗證 Node.js 型應用程式的功能

您終於可以測試 Web 應用程式的功能了。 雖然您可以將其容器化,但為了簡單起見,請將其部署至 Azure App Service。 這可讓您快速驗證其功能,並確定是否可以將其容器化。

  1. 在 [Cloud Shell] 窗格上的 Bash 工作階段中執行下列命令,以建立將會裝載 Azure Web 應用程式的資源群組,並於其中部署 Node.js Express 應用程式:

    RG1NAME=postgresql-db-RG
    LOCATION=$(az group show --resource-group $RG1NAME --query location --output tsv)
    RG2NAME=cna-aadexpress-RG
    az group create --name $RG2NAME --location $LOCATION
    
  2. 執行下列命令,以建立將會裝載新 Azure Web 應用程式的免費層 Azure App Service 方案:

    SPNAME=aadexpress-sp
    az appservice plan create --name $SPNAME --resource-group $RG2NAME --sku F1 --is-linux
    
  3. 執行下列命令,以建立新的 Node.js 型 Azure Web 應用程式:

    WEBAPPNAME=aadexpress$RANDOM$RANDOM
    az webapp create --name $WEBAPPNAME --resource-group $RG2NAME --plan $SPNAME --runtime "NODE|16-lts"
    
  4. 執行下列命令,以識別 Web 應用程式的名稱:

    echo $WEBAPPNAME
    
  5. 使用 nano 編輯器開啟 index.js 檔案,以您在上一個步驟中識別的名稱取代兩個 <webapp_name> 預留位置,儲存變更,然後關閉檔案。

    注意

    請務必取代這兩個 <webapp_name> 預留位置。

  6. 在顯示 Azure 入口網站的網頁瀏覽器視窗中開啟另一個索引標籤,巡覽至 Azure 入口網站,並在出現提示時登入,以存取您將在本課程模組中使用的 Azure 訂閱。

  7. 在 Azure 入口網站中,使用 [搜尋資源、服務和文件] 文字輸入框,搜尋 Microsoft Entra ID,然後在結果清單中選取 [Microsoft Entra ID]

  8. 在 [Microsoft Entra] 刀鋒視窗上,巡覽至 [應用程式註冊] 刀鋒視窗,選取 [cna-app] 項目,然後在垂直功能表的 [管理] 區段中選取 [驗證]。

  9. 在 [cna-app | 驗證] 刀鋒視窗上,修改 [重新導向 URI] 的值以符合您在 index.js 檔案中更新的項目,然後儲存變更。

    Screenshot of the cna-app Authentication blade in the Azure portal.

  10. 切換回顯示 [Cloud Shell] 窗格上 Bash 工作階段的網頁瀏覽器索引標籤,然後執行下列命令,將本機 Git 存放庫初始化並認可主分支中的所有變更:

    cd ~/cna-aadexpress
    git config --global user.email "user1@adatum.com"
    git config --global user.name "Adatum User1"
    git init
    git add -A
    git commit -m "Initial Commit"
    
  11. 執行下列命令,以設定使用者層級的部署認證:

    DEPLOYMENTUSER=m06User$RANDOM
    DEPLOYMENTPASS=m06Pass$RANDOM$RANDOM
    az webapp deployment user set --user-name $DEPLOYMENTUSER --password $DEPLOYMENTPASS
    
  12. 執行下列命令,以識別使用者層級的部署認證並記錄其值,因為稍後會在此工作中用到這些認證:

    echo $DEPLOYMENTUSER
    echo $DEPLOYMENTPASS
    
  13. 執行下列命令,以識別將用作 git push 命令目標的 Azure Web 應用程式部署 URL:

    RG2NAME=cna-aadexpress-RG
    WEBAPPNAME=$(az webapp list --resource-group $RG2NAME --query "[0].name" --output tsv)
    DEPLOYMENTURL=$(az webapp deployment source config-local-git --name $WEBAPPNAME --resource-group $RG2NAME --output tsv)
    
  14. 執行下列命令來設定名為 azure 的遠端存放庫,以代表您在上一個步驟中識別的部署 URL:

    git remote add azure $DEPLOYMENTURL
    
  15. 執行下列命令以根據分支建立測試分支,並將其內容推送至 Azure Web 應用程式 (當提示輸入的密碼屬於先前在此工作中記錄的使用者層級部署認證時):

    git checkout -b test
    git commit -a -m "testing"
    git push --set-upstream azure test
    
  16. 關閉 [Cloud Shell] 窗格。

  17. 以無痕/InPrivate 模式開啟另一個網頁瀏覽器視窗,巡覽至 Azure 入口網站,並使用在上一個練習中建立的 adatumuser1 使用者帳戶登入。

  18. 在 Azure 入口網站中,使用 Azure 入口網站頁面頂端的 [搜尋資源、服務及文件] 文字輸入框搜尋 應用程式服務

  19. 在 [App Service] 刀鋒視窗的 App Service 執行個體清單中,選取代表新部署的 Azure Web 應用程式的項目。

  20. 在顯示 Web 應用程式屬性的窗格上,在 [基本資訊] 區段,複製 [預設網域] URL 的值。

  21. 在相同的瀏覽器視窗中開啟另一個索引標籤,然後在其搜尋方塊中輸入 https://,貼上您剛才複製到剪貼簿的 URL,並新增 /auth 尾碼,然後選取 Enter。

    注意

    URL 應具有下列格式:https://<webapp_name>.azurewebsites.net/auth

  22. 確認產生的網頁包含目前登入使用者的 Microsoft Entra 驗證資訊 (輸出可能會有所不同)。

    Screenshot of the page of the Node.js web app displaying the Microsoft Entra authentication information.

結果

恭喜! 您已完成本課程模組的第二個練習。 在此練習中,您已在單一伺服器部署模型中安裝適用於 PostgreSQL 的 Azure 資料庫、使用範例清查資料建立資料庫、將伺服器與 Microsoft Entra ID 整合,並實作簡單的 Node.js 型應用程式以查詢依賴 Microsoft Entra 驗證的資料庫。