練習 - 使用共用存取簽章來委派對 Azure 儲存體的存取權
Azure 儲存體讓您能夠以共用金鑰、共用存取簽章 (SAS) 或 Microsoft Entra ID 授與檔案的存取權。 使用 SAS,您可以控制用戶端能對檔案執行的動作,以及時間長短。
貴公司的影像診斷系統會透過共用金鑰在內部存取其患者影像。 您需要建立 API,讓協力廠商能夠存取診斷影像。 您會在自己的 Web 應用程式上建立測試頁面,以查看 SAS 如何協助您為協力廠商用戶端授與安全的存取權。
在此練習中,您會建立一個儲存體帳戶,並上傳一些範例患者影像。 您會部署小組現有的 Web 應用程式,並測試此應用程式能否存取儲存體。 最後一個步驟是新增 C# 與 JavaScript 程式碼,隨需產生 SAS 權杖以安全地檢視影像。
建立儲存體帳戶及上傳影像
在畫面右側的 Cloud Shell 視窗,選取 [更多] 圖示 ([...]),然後選取 [設定] > [前往傳統版本]。
使用 Azure Cloud Shell,輸入下列程式碼,以建立患者影像的儲存體帳戶。 程式碼會產生儲存體帳戶名稱。
export STORAGENAME=medicalrecords$RANDOM az storage account create \ --name $STORAGENAME \ --access-tier hot \ --kind StorageV2 \ --resource-group "<rgn>[sandbox resource group name]</rgn>"
在儲存體帳戶底下,建立用來儲存影像的容器。
az storage container create \ --name patient-images \ --account-name $STORAGENAME \ --public-access off
複製小組現有的 Web 應用程式。 此存放庫包含小組用來測試的範例影像。
git clone https://github.com/MicrosoftDocs/mslearn-control-access-to-azure-storage-with-sas.git sas
使用 Azure CLI 的 upload-batch 命令,將影像上傳至您的儲存體帳戶。
az storage blob upload-batch \ --source sas \ --destination patient-images \ --account-name $STORAGENAME \ --pattern *.jpg
測試患者診斷影像系統
在程式碼編輯器中,開啟 appsettings.json 檔案,以便新增儲存體帳戶的連接字串。
code sas/appsettings.json
在 Cloud Shell 中,輸入下列程式碼,以取得儲存體帳戶的連接字串。
az storage account show-connection-string --name $STORAGENAME
您應該會看到下列格式的回應:
{ "connectionString": "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=<account-name>;AccountKey=<account-key>" }
複製 connectionString 值,包括引號。
在程式碼編輯器中,將 ConnectionString 值
"[connection string]"
取代為您複製的字串。複製連接字串主體中
AccountName=
的值。將 AccountName 參數的值取代為您複製的帳戶名稱值。
複製連接字串主體中
AccountKey=
的值 (不包含引號)。 務必在值結尾包含==
。將 AccountKey 參數的值取代為您複製的帳戶金鑰值。
appsettings.json 檔案現在看起來應該類似這個輸出。
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "StorageAccount": { "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=<account-name>;AccountKey=<account-key>;EndpointSuffix=core.windows.net", "Container" : "patient-images", "AccountName":"<account-name>", "AccountKey":"<account-key>" } }
選取 Ctrl+S,然後選取 Ctrl+Q,以儲存並關閉程式碼編輯器。
開啟連接埠,以便您可以 Web 應用程式在 Cloud Shell 中執行時,存取 Web 應用程式。
curl -X POST http://localhost:8888/openPort/8000;
此命令會傳回可在其中存取您應用程式的
url
。{"message":"Port 8000 is open","url":"https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/"}
執行應用程式。
cd sas dotnet run
編譯應用程式之後,Cloud Shell 主控台會顯示類似下列範例的詳細資料。
Hosting environment: Development Content root path: /home/<yourusername>/sas Now listening on: https://localhost:8001 Now listening on: http://localhost:8000 Application started. Press Ctrl+C to shut down.
在瀏覽器中,貼上先前的 cURL 命令所傳回的 URL。 確定位址的結尾包含正斜線 (/)。
URL 應該是此格式:
https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/
。如果系統提示您登入,請重新整理瀏覽器視窗。 Lamna 醫療保健患者診斷影像系統隨即出現。
選取 [Get all patients] \(取得所有患者資料\),以檢視儲存在儲存體帳戶中的所有影像。
新增程式碼以建立 SAS
在 Cloud Shell 中,選取 Ctrl+C 以停止 Web 應用程式。
讓我們增強 PatientRecordController 類別以建立隨需 SAS,並將其傳回至 Web 應用程式的前端。
輸入下列程式碼,以在程式碼編輯器中開啟 PatientRecordController.cs 檔案。
code Controllers/PatientRecordController.cs
將下列程式碼新增至
GET PatientRecord/patient-nnnnnn
方法下的類別底部。// GET PatientRecord/patient-nnnnnn/secure [HttpGet("{Name}/{secure}")] public PatientRecord Get(string name, string flag) { BlobClient blob = _container.GetBlobClient(name); return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri, sasToken=GetBlobSas(blob) }; }
此方法會傳回所要求的患者影像,以及可用來存取該影像的 SAS。
新增將為 Blob 建立 SAS 的方法。
// Build a SAS token for the given blob private string GetBlobSas(BlobClient blob) { // Create a user SAS that only allows reading for a minute BlobSasBuilder sas = new BlobSasBuilder { BlobContainerName = blob.BlobContainerName, BlobName = blob.Name, Resource = "b", ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1) }; // Allow read access sas.SetPermissions(BlobSasPermissions.Read); // Use the shared key to access the blob var storageSharedKeyCredential = new StorageSharedKeyCredential( _iconfiguration.GetValue<string>("StorageAccount:AccountName"), _iconfiguration.GetValue<string>("StorageAccount:AccountKey") ); return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString(); }
此方法會使用傳遞的
BlobClient
物件來建立BlobSasBuilder
,以產生唯讀的 SAS,並在一分鐘內到期。選取 Ctrl+S 以儲存檔案,然後選取 Ctrl+Q 以結束編輯器。
新增程式碼以使用 SAS
讓我們將程式碼新增至網頁,以要求影像的 SAS。
輸入下列命令,以編輯 external.cshtml 頁面。
code Pages/external.cshtml
在檔案結尾附近,在
#btn-submit
的點選接聽程式中,修改$.get
行以新增+ '/secure'
:$('#btn-submit').click(function(){ $('#result').empty(); $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) { var imageURL = data.imageURI + $('#sasKey').val(); $('#result').html('<img id="patientScan" class="alert alert-success" src="' + imageURL + '" alt="patient scan" onerror="this.classList.remove(\'alert-success\'); this.classList.add(\'alert-danger\')"//>'); }, 'json'); });
在檔案底部的
#btn-submit
點選接聽程式函式下方,於</script>
標籤上方,新增下列程式碼:$('#btn-getKey').click(function(){ $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) { $('#sasKey').val(data.sasToken); }, 'json'); });
此 jQuery 程式碼會在
btn-getKey
按鈕上新增 click 接聽程式。 此程式碼會對適用於指定影像檔案的新安全 URL 執行 Ajax 呼叫。 當其傳回時,會在金鑰輸入方塊中填入 SAS。選取 Ctrl+S 以儲存變更,然後選取 Ctrl+Q 以結束編輯器。
測試變更
執行已更新的應用程式。
dotnet run
在瀏覽器中,重新整理網站的索引標籤。 選取 [Get all patients] \(取得所有患者資料\),然後複製其中一個影像檔案名稱。
在網頁頂端的功能表中,選取 [External companies] \(外部公司\)。
將檔案名稱貼入 [Patient image filename] (患者影像檔案名稱) 欄位。
選取 [檢視掃描]。 因為您尚未建立 SAS,所以無法存取患者掃描影像。
注意
如果您在瀏覽器中檢視主控台,即會看到 Web 伺服器傳回 404 錯誤碼訊息。
選取 [取得金鑰],這應該用 SAS 來填入 [金鑰] 欄位。
選取 [檢視掃描]。 患者的診斷影像應該會隨即出現。
在瀏覽器中,以滑鼠右鍵按一下影像,然後複製影像位址。
開啟新的瀏覽器索引標籤、在網址列中貼上複製的影像位址,然後按 Enter。 如果自您建立 SAS 後已超過一分鐘,您應會看到一則錯誤訊息。 如果小於一分鐘,則應會顯示影像。
注意
您可能需要重新整理網頁。
<Error> <Code>AuthenticationFailed</Code> <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly, including the signature. RequestId:03eda893-f01e-0028-2d73-c5c947000000 Time:2021-01-07T16:02:55.3752851Z</Message> <AuthenticationErrorDetail>Signed expiry time [Tue, 07 Jan 2021 16:02:00 GMT] must be after signed start time [Tue, 07 Jan 2021 16:02:55 GMT]</AuthenticationErrorDetail> </Error>
注意
若要從某些瀏覽器檢視此錯誤訊息,您可能需要開啟不會快取影像的新瀏覽器視窗。
在 Cloud Shell 中,選取 Ctrl+C 以結束 Web 應用程式。