在本教學課程中,您會將 Django Web 應用程式部署至 Azure App 服務。 網頁應用程式會使用使用者指派的管理識別(無密碼連線)搭配 Azure 角色型訪問控制來存取Azure 儲存體和適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器資源。 此程式碼使用 Python 的 Azure 身分識別用戶端程式庫 中的 DefaultAzureCredential 類別。 類別 DefaultAzureCredential 會自動偵測 App Service 的受控識別是否存在,並用它來存取其他 Azure 資源。
在本教學課程中,您會建立使用者指派的受控識別,並將其指派給 App Service,以便存取資料庫和記憶體帳戶資源。 如需使用系統指派受控識別的範例,請參閱 使用系統指派的受控識別建立和部署 Flask Python Web 應用程式至 Azure。 建議使用使用者指派的受控識別,因為它們可供多個資源使用,而且其生命週期會與與其相關聯的資源生命周期分離。 如需使用受控識別最佳做法的詳細資訊,請參閱 受控識別最佳做法建議。
本教學課程將說明如何部署 Python Web 應用程式,並使用 Azure CLI 建立 Azure 資源。 雖然本教學課程中的命令會使用 Bash Shell,但您可以在任何已安裝 CLI 的 Bash 環境中執行教學課程命令,例如本機環境或 Azure Cloud Shell。 透過一些修改,您可以在其他環境中執行這些命令,例如 Windows 命令殼層 (例如修改語法以設定和使用環境變數)。
取得範例應用程式
使用範例 Django 範例應用程式來遵循本教學課程。 下載或複製範例應用程式到您的開發環境。
複製範例。
git clone https://github.com/Azure-Samples/msdocs-django-web-app-managed-identity.git瀏覽至應用程式資料夾。
cd msdocs-django-web-app-managed-identity
檢查驗證碼
範例 Web 應用程式必須向兩個不同的資料存放區進行驗證:
- Azure Blob 記憶體伺服器會儲存並擷取檢閱者提交的相片。
- 適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器資料庫,其儲存餐廳與評論。
它使用DefaultAzureCredential來驗證這兩個數據存放區。 使用 DefaultAzureCredential時,應用程式可以設定為在不同的服務主體身分識別下執行,視其執行環境而定,而不需變更程式碼。 例如,在本機開發環境中,應用程式可以在登入 Azure CLI 的開發人員身分識別下執行,而在 Azure 中,如本教學課程所示,它可以在使用者指派的受控識別下執行。
不論是哪一種情況,應用程式執行的安全性主體都必須在應用程式所使用的每個 Azure 資源上具有角色,才能在應用程式所需的資源上執行動作。 在本教學課程中,您會使用 Azure CLI 命令來建立使用者指派的受控識別,並將它指派給 Azure 中的應用程式。 然後,您需在 Azure 儲存體帳戶和 Azure PostgreSQL 資料庫伺服器上,手動為這個身分識別指派適當的角色。 最後,您要在 Azure 中為應用程式設定 AZURE_CLIENT_ID 環境變數,以配置 DefaultAzureCredential 使用受控識別。
在應用程式及其執行階段環境中設定使用者指派的受控識別,並在資料存放庫上指派適當的角色之後,您可以使用 DefaultAzureCredential 來向所需的 Azure 資源進行驗證。
以下程式碼用於建立 Blob 儲存體用戶端,以便在 ./restaurant_review/views.py 上傳相片。 使用者會獲得一個 DefaultAzureCredential 的實例,以用來取得存取令牌,從而對 Azure 儲存體執行作業。
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
azure_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url=account_url,
credential=azure_credential)
在DefaultAzureCredential中,DefaultAzureCredential實例也可用來取得適用於PostgreSQL的Azure資料庫存取令牌。 在此情況下,令牌會直接透過在憑證實例上呼叫 get_token,並傳遞適當的 scope 值來取得。 令牌接著會用來在PostgreSQL連線 URI 中設定密碼。
azure_credential = DefaultAzureCredential()
token = azure_credential.get_token("https://ossrdbms-aad.database.windows.net")
conf.settings.DATABASES['default']['PASSWORD'] = token.token
若要深入瞭解如何使用適用於 Python 的 Azure SDK 來驗證您的 Python 應用程式與 Azure 服務之間的身份,請參閱 使用適用於 Python 的 Azure SDK 驗證 Azure 服務上的 Python 應用程式。 若要深入瞭解 DefaultAzureCredential,包括如何針對您的環境自訂其評估的認證鏈結,請參閱 DefaultAzureCredential 概觀。
建立 Azure PostgreSQL 彈性伺服器
設定教學課程所需的環境變數。
LOCATION="eastus" RAND_ID=$RANDOM RESOURCE_GROUP_NAME="msdocs-mi-web-app" APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID" DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID" ADMIN_USER="demoadmin" ADMIN_PW="ChAnG33#ThsPssWD$RAND_ID" UA_NAME="UAManagedIdentityPythonTest$RAND_ID"重要
ADMIN_PW必須包含以下三個類別中的8到128個字元:英文大寫字母、英文小寫字母、數字和非字母數字字元。 當建立使用者名稱或密碼時,請不要使用 字元。 稍後您可以使用這些值建立環境變數,其中$字元在用來執行 Python 應用程式的 Linux 容器中具有特殊意義。使用 az group create 命令來建立資源群組。
az group create --location $LOCATION --name $RESOURCE_GROUP_NAME使用 az postgres flexible-server create 命令建立 PostgreSQL 彈性伺服器。 (這個和後續的命令會使用 Bash Shell 的行接續字元 '\')。 變更其他 shell 的換行字元。
az postgres flexible-server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --location $LOCATION \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --sku-name Standard_D2ds_v4 \ --active-directory-auth Enabled \ --public-access 0.0.0.0sku-name 是定價層和計算組態的名稱。 如需更多資訊,請參閱Azure Database for PostgreSQL 定價。 若要列出可用的 SKU,請使用
az postgres flexible-server list-skus --location $LOCATION。使用 az postgres flexible-server ad-admin create 命令,將您的 Azure 帳戶新增為伺服器的 Microsoft Entra 管理員。
ACCOUNT_EMAIL=$(az ad signed-in-user show --query userPrincipalName --output tsv) ACCOUNT_ID=$(az ad signed-in-user show --query id --output tsv) echo $ACCOUNT_EMAIL, $ACCOUNT_ID az postgres flexible-server ad-admin create \ --resource-group $RESOURCE_GROUP_NAME \ --server-name $DB_SERVER_NAME \ --display-name $ACCOUNT_EMAIL \ --object-id $ACCOUNT_ID \ --type User使用 az postgres flexible-server firewall-rule create 命令,在您的伺服器上設定防火牆規則。 此規則可讓您的本機環境存取權連線到伺服器。 (如果您使用 Azure Cloud Shell,您可以略過此步驟。
IP_ADDRESS=<your IP> az postgres flexible-server firewall-rule create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --rule-name AllowMyIP \ --start-ip-address $IP_ADDRESS \ --end-ip-address $IP_ADDRESS使用任何顯示您IP位址的工具或網站,以取代命令中的
<your IP>。 例如,您可以使用 「我的 IP 位址是什麼?」 網站。使用命令 az postgres flexible-server execute 建立名為
restaurant的資料庫。az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --database-name postgres \ --querytext 'create database restaurant;'
建立 Azure App 服務並部署程序代碼
若要建立 App Service 並部署程式碼,請在範例應用程式的根資料夾中執行這些命令。
使用 az webapp up 命令建立 App Service。
az webapp up \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --name $APP_SERVICE_NAME \ --runtime PYTHON:3.9 \ --sku B1SKU 會定義 App Service 方案的大小(CPU、記憶體)和成本。 B1 (基本) 服務方案會在您的 Azure 訂用帳戶中產生少量成本。 如需 App Service 方案的完整清單,請查看 App Service 定價頁面。
將 App Service 設定為使用範例存放庫中的 start.sh,並使用 az webapp config set 命令。
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
建立儲存體帳戶和容器
範例應用程式會將檢閱者提交的相片儲存為 Azure 儲存體 中的 Blob。
當使用者將相片與評論一起提交時,範例應用程式會使用受控身分識別和 DefaultAzureCredential 將影像寫入容器,以存取儲存體帳戶。
當用戶檢視餐廳的評論時,應用程式會針對每個與該評論相關聯的檢閱,傳回 Blob 記憶體中相片的連結。 若要讓瀏覽器顯示相片,它必須能夠在記憶體帳戶中存取它。 Blob 數據必須可供透過匿名(未經驗證)存取公開讀取。
在本節中,您會建立記憶體帳戶和容器,以允許對容器中的 Blob 進行公用讀取存取。 在稍後的章節中,您會建立使用者指派的受控識別,並將其設定為將 Blob 寫入記憶體帳戶。
使用 az storage create 命令來建立儲存帳戶。
STORAGE_ACCOUNT_NAME="msdocsstorage$RAND_ID" az storage account create \ --name $STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --sku Standard_LRS \ --allow-blob-public-access true使用 az storage container create 命令,在儲存帳戶中建立一個名為 photos 的容器。
az storage container create \ --account-name $STORAGE_ACCOUNT_NAME \ --name photos \ --public-access blob \ --auth-mode login注意
命令可能會失敗。 例如,您可能會收到錯誤,指出網路規則正在封鎖建立儲存體帳戶的要求。 如果命令失敗,請輸入下列命令,以確保將具有建立容器許可權的 Azure 角色指派給您的 Azure 使用者帳戶。
az role assignment create --role "Storage Blob Data Contributor" --assignee $ACCOUNT_EMAIL --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"如需詳細資訊,請參閱 快速入門:使用 Azure CLI 建立、下載及列出 Blob。 數個 Azure 角色可讓您在儲存體帳戶中建立容器,包括 擁有者、 參與者、 儲存體 Blob 資料擁有者和 儲存體 Blob 資料參與者。
建立使用者指派的管理型身分識別
建立使用者指派的受控識別,並將它指派給App Service。 受控識別可用來存取資料庫和記憶體帳戶。
使用 az identity create 命令來建立使用者自訂的受控識別,並將客戶端 ID 輸出到變數中以供稍後使用。
UA_CLIENT_ID=$(az identity create --name $UA_NAME --resource-group $RESOURCE_GROUP_NAME --query clientId --output tsv) echo $UA_CLIENT_ID使用 az account show 命令來取得您的訂用帳戶 ID,並將其輸出到可用來構建受控身份的資源 ID 的變數。
SUBSCRIPTION_ID=$(az account show --query id --output tsv) RESOURCE_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$UA_NAME" echo $RESOURCE_ID使用 az webapp identity assign 命令將受控身份指派給 App Service。
export MSYS_NO_PATHCONV=1 az webapp identity assign \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --identities $RESOURCE_ID使用 az webapp config appsettings set 命令建立包含受控識別用戶端識別碼和其他配置資訊的 App Service 應用程式設定。
az webapp config appsettings set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --settings AZURE_CLIENT_ID=$UA_CLIENT_ID \ STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME \ STORAGE_CONTAINER_NAME=photos \ DBHOST=$DB_SERVER_NAME \ DBNAME=restaurant \ DBUSER=$UA_NAME
範例應用程式會使用環境變數(應用程式設定)來定義資料庫和記憶體帳戶的連線資訊,但這些變數不包含密碼。 反而,使用DefaultAzureCredential進行無密碼驗證。
範例應用程式程式碼使用 DefaultAzureCredential 類別的建構函式,但未將使用者指派的受控識別客戶端 ID 傳遞至該建構函式。 在此案例中,後備方案是檢查您設定為應用程式設定的 AZURE_CLIENT_ID 環境變數。
如果環境變數不存在,則 AZURE_CLIENT_ID 會使用系統指派的受控識別(如果已設定)。 如需詳細資訊,請參閱「詳介 DefaultAzureCredential」。
建立管理型身分識別的角色
在本節中,您會為受控識別建立角色指派,以啟用記憶體帳戶和資料庫的存取權。
使用「az role assignment create」命令為受控身分識別建立角色指派,以啟用對儲存體帳戶的存取權。
export MSYS_NO_PATHCONV=1 az role assignment create \ --assignee $UA_CLIENT_ID \ --role "Storage Blob Data Contributor" \ --scope "/subscriptions/$SUBSCRIPTION_ID/resourcegroups/$RESOURCE_GROUP_NAME"命令會指定資源群組的角色指派範圍。 如需詳細資訊,請參閱 瞭解角色指派。
使用 az postgres flexible-server execute 命令連線到 Postgres 資料庫,並執行相同的操作,將角色指派給受控識別。
ACCOUNT_EMAIL_TOKEN=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken) az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ACCOUNT_EMAIL \ --admin-password $ACCOUNT_EMAIL_TOKEN \ --database-name postgres \ --querytext "select * from pgaadauth_create_principal('"$UA_NAME"', false, false);select * from pgaadauth_list_principals(false);"如果您在執行命令時遇到問題,請確定您已將使用者帳戶新增為 PosgreSQL 伺服器的 Microsoft Entra 系統管理員,並允許在防火牆規則中存取您的 IP 位址。 如需詳細資訊,請參閱建立 Azure PostgreSQL 彈性伺服器一節。
在 Azure 中測試 Python Web 應用程式
範例 Python 應用程式會使用 azure.identity 套件及其 類別。 當應用程式在 Azure 中執行時,DefaultAzureCredential 會自動偵測 App Service 是否有受控識別存在,如果是的話,並使用它來存取其他 Azure 資源(在此案例中為儲存體和 PostgreSQL)。 不需要提供記憶體金鑰、憑證或認證給 App Service,才能存取這些資源。
流覽至已部署應用程式的 URL
http://$APP_SERVICE_NAME.azurewebsites.net。應用程式可能需要一兩分鐘的時間才能啟動。 如果您看到預設的應用程式頁面不是預設範例應用程式頁面,請稍候一分鐘並重新整理瀏覽器。
藉由新增餐廳以及一些具有餐廳相片的評論,測試範例應用程式的功能。
餐廳和評論資訊儲存在 適用於 PostgreSQL 的 Azure 資料庫,照片儲存在 Azure 儲存體。 以下是範例螢幕快照:
範例應用程式的螢幕快照,其中顯示使用 Azure App 服務、Azure Postgre SQL 資料庫 和 Azure 儲存體 的餐廳檢閱功能。
清理
在本教學課程中,所有 Azure 資源都是在相同的資源群組中建立的。 使用 az group delete 命令會移除資源群組及其內所有的資源,這是最快移除應用程式所需所有 Azure 資源的方法。
az group delete --name $RESOURCE_GROUP_NAME
您可以選擇性地新增 --no-wait 引數,以允許命令在作業完成之前傳回。
下一步
使用系統指派的受控身分建立並部署 Flask Web 應用程式到 Azure
在 Azure App Service 中使用 PostgreSQL 部署 Python(Django 或 Flask)Web 應用程式