問題描述
在使用Azure儲存服務,為了有效的保護Storage的Access Keys。可以使用另一種授權方式訪問資源(Shared Access Signature: 共享訪問簽名), 它的好處可以控制允許訪問的IP,過期時間,許可權 和 服務 等。Azure門戶上提供了對Account級,Container級,Blob級的SAS生成服務。
那麼使用程式碼如何來生成呢?
問題回答
以最常見的兩種程式碼作為示例:.NET 和 Java
.NET
Blob SAS 將使用帳戶訪問金鑰(Storage Account Key1 or Key2)進行簽名。 使用 StorageSharedKeyCredential 類建立用於為 SAS 簽名的憑據。 新建 BlobSasBuilder 物件,並呼叫 ToSasQueryParameters 以獲取 SAS 令牌字串。官方文件(https://docs.azure.cn/zh-cn/storage/blobs/sas-service-create?tabs=dotnet)中進行了詳細介紹,直接使用以下部分程式碼即可生成Blob的SAS URL。
private static Uri GetServiceSasUriForBlob(BlobClient blobClient, string storedPolicyName = null) { // Check whether this BlobClient object has been authorized with Shared Key. if (blobClient.CanGenerateSasUri) { // Create a SAS token that's valid for one hour. BlobSasBuilder sasBuilder = new BlobSasBuilder() { BlobContainerName = blobClient.GetParentBlobContainerClient().Name, BlobName = blobClient.Name, Resource = "b" }; if (storedPolicyName == null) { sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1); sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write); } else { sasBuilder.Identifier = storedPolicyName; } Uri sasUri = blobClient.GenerateSasUri(sasBuilder); Console.WriteLine("SAS URI for blob is: {0}", sasUri); Console.WriteLine(); return sasUri; } else { Console.WriteLine(@"BlobClient must be authorized with Shared Key credentials to create a service SAS."); return null; } }
JAVA
而Java的示例程式碼在官網中並沒有介紹,所以本文就Java生成SAS的程式碼進行講解。
從Java新版的SDK(azure-storage-blob)中 ,可以發現 BlobServiceClient,BlobContainerClient ,BlobClient 物件中都包含 generateAccountSas 或 generateSas 方法來實現對Account, Container,Blob進行SAS Token生成,只需要根據它所需要的引數對
public static void GenerateSASstring(BlobServiceClient blobServiceClient, BlobContainerClient blobContainerClient, BlobClient blobClient) { /* * Generate an account sas. Other samples in this file will demonstrate how to * create a client with the sas token. */ // Configure the sas parameters. This is the minimal set. OffsetDateTime startTime = OffsetDateTime.now(); OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1); AccountSasService services = new AccountSasService().setBlobAccess(true); AccountSasResourceType resourceTypes = new AccountSasResourceType().setObject(true); SasProtocol protocol = SasProtocol.HTTPS_ONLY; SasIpRange sasIpRange = SasIpRange.parse("167.220.255.73"); // Generate the account sas. AccountSasPermission accountSasPermission = new AccountSasPermission().setReadPermission(true); AccountSasSignatureValues accountSasValues = new AccountSasSignatureValues(expiryTime, accountSasPermission, services, resourceTypes); accountSasValues.setStartTime(startTime); accountSasValues.setProtocol(protocol); accountSasValues.setSasIpRange(sasIpRange); String accountSasToken = blobServiceClient.generateAccountSas(accountSasValues); System.out.println("\nGenerate the account sas & url is :::: \n\t" + accountSasToken + "\n\t" + blobServiceClient.getAccountUrl() + "?" + accountSasToken); // Generate a sas using a container client BlobContainerSasPermission containerSasPermission = new BlobContainerSasPermission().setCreatePermission(true); BlobServiceSasSignatureValues serviceSasValues = new BlobServiceSasSignatureValues(expiryTime, containerSasPermission); serviceSasValues.setStartTime(startTime); serviceSasValues.setProtocol(protocol); serviceSasValues.setSasIpRange(sasIpRange); String containerSasToken = blobContainerClient.generateSas(serviceSasValues); System.out.println("\nGenerate the Container sas & url is :::: \n\t" + containerSasToken + "\n\t" + blobContainerClient.getBlobContainerUrl() + "?" + containerSasToken); // Generate a sas using a blob client BlobSasPermission blobSasPermission = new BlobSasPermission().setReadPermission(true); serviceSasValues = new BlobServiceSasSignatureValues(expiryTime, blobSasPermission); serviceSasValues.setStartTime(startTime); serviceSasValues.setProtocol(protocol); serviceSasValues.setSasIpRange(sasIpRange); String blobSasToken = blobClient.generateSas(serviceSasValues); System.out.println("\nGenerate the Blob sas & url is :::: \n\t" + blobSasToken + "\n\t" + blobClient.getBlobUrl() + "?" + blobSasToken); }
在pom.xml 中所需要載入的依賴項:
<dependency> <groupId>com.azure</groupId> <artifactId>azure-storage-blob</artifactId> <version>12.13.0</version> </dependency>
以上程式碼中的各部分設定項 與 Azure門戶上設定項的對應關係如下圖:
執行效果圖
附錄一:Java Main函式全部程式碼:
package test; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.net.URISyntaxException; import java.security.InvalidKeyException; import java.time.OffsetDateTime; import java.util.Iterator; import com.azure.storage.blob.BlobClient; import com.azure.storage.blob.BlobContainerClient; import com.azure.storage.blob.BlobServiceClient; import com.azure.storage.blob.BlobServiceClientBuilder; import com.azure.storage.blob.models.BlobItem; import com.azure.storage.blob.sas.BlobContainerSasPermission; import com.azure.storage.blob.sas.BlobSasPermission; import com.azure.storage.blob.sas.BlobServiceSasSignatureValues; import com.azure.storage.common.sas.AccountSasPermission; import com.azure.storage.common.sas.AccountSasResourceType; import com.azure.storage.common.sas.AccountSasService; import com.azure.storage.common.sas.AccountSasSignatureValues; import com.azure.storage.common.sas.SasIpRange; import com.azure.storage.common.sas.SasProtocol; /** * Hello world! * */ public class App { public static void main(String[] args) throws URISyntaxException, InvalidKeyException, RuntimeException, IOException { System.out.println("Hello World!"); String storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=<your storage account name>;AccountKey=**************************;EndpointSuffix=core.chinacloudapi.cn"; String blobContainerName = "test"; String dirName = ""; // Create a BlobServiceClient object which will be used to create a container System.out.println("\nCreate a BlobServiceClient Object to Connect Storage Account"); BlobServiceClient blobServiceClient = new BlobServiceClientBuilder().connectionString(storageConnectionString) .buildClient(); // Create a unique name for the container String containerName = blobContainerName + java.util.UUID.randomUUID(); // Create the container and return a container client object System.out.println("\nCreate new Container : " + containerName); BlobContainerClient containerClient = blobServiceClient.createBlobContainer(containerName); // Create a local file in the ./data/ directory for uploading and downloading System.out.println("\nCreate a local file in the ./data/ directory for uploading and downloading"); String localPath = "./data/"; String fileName = "quickstart" + java.util.UUID.randomUUID() + ".txt"; File localFile = new File(localPath + fileName); // Write text to the file FileWriter writer = new FileWriter(localPath + fileName, true); writer.write("Hello, World! This is test file to download by SAS. Also test upload"); writer.close(); // Get a reference to a blob BlobClient blobClient = containerClient.getBlobClient(fileName); System.out.println("\nUploading to Blob storage as blob:\n\t" + blobClient.getBlobUrl()); // Upload the blob blobClient.uploadFromFile(localPath + fileName); System.out.println("\nUpload blob completed : " + blobClient.getBlobName()); System.out.println("\nListing blobs..."); // List the blob(s) in the container. for (BlobItem blobItem : containerClient.listBlobs()) { System.out.println("\t" + blobItem.getName()); } // Download the blob to a local file // Append the string "DOWNLOAD" before the .txt extension so that you can see // both files. String downloadFileName = fileName.replace(".txt", "DOWNLOAD.txt"); File downloadedFile = new File(localPath + downloadFileName); System.out.println("\nDownloading blob to\n\t " + localPath + downloadFileName); blobClient.downloadToFile(localPath + downloadFileName); // Generate SAS String for blob user.. System.out.println("\nGenerate SAS String for blob user.."); GenerateSASstring(blobServiceClient, containerClient, blobClient); // Clean up System.out.println("\nPress the Enter word 'Delete' to begin clean up"); boolean isDelete = System.console().readLine().toLowerCase().trim().equals("delete"); if (isDelete) { System.out.println("Deleting blob container..."); containerClient.delete(); System.out.println("Deleting the local source and downloaded files..."); localFile.delete(); downloadedFile.delete(); } else { System.out.println("Skip to Clean up operation"); } System.out.println("Done"); } public static void GenerateSASstring(BlobServiceClient blobServiceClient, BlobContainerClient blobContainerClient, BlobClient blobClient) { /* * Generate an account sas. Other samples in this file will demonstrate how to * create a client with the sas token. */ // Configure the sas parameters. This is the minimal set. OffsetDateTime startTime = OffsetDateTime.now(); OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1); AccountSasService services = new AccountSasService().setBlobAccess(true); AccountSasResourceType resourceTypes = new AccountSasResourceType().setObject(true); SasProtocol protocol = SasProtocol.HTTPS_ONLY; SasIpRange sasIpRange = SasIpRange.parse("167.220.255.73"); // Generate the account sas. AccountSasPermission accountSasPermission = new AccountSasPermission().setReadPermission(true); AccountSasSignatureValues accountSasValues = new AccountSasSignatureValues(expiryTime, accountSasPermission, services, resourceTypes); accountSasValues.setStartTime(startTime); accountSasValues.setProtocol(protocol); accountSasValues.setSasIpRange(sasIpRange); String accountSasToken = blobServiceClient.generateAccountSas(accountSasValues); System.out.println("\nGenerate the account sas & url is :::: \n\t" + accountSasToken + "\n\t" + blobServiceClient.getAccountUrl() + "?" + accountSasToken); // Generate a sas using a container client BlobContainerSasPermission containerSasPermission = new BlobContainerSasPermission().setCreatePermission(true); BlobServiceSasSignatureValues serviceSasValues = new BlobServiceSasSignatureValues(expiryTime, containerSasPermission); serviceSasValues.setStartTime(startTime); serviceSasValues.setProtocol(protocol); serviceSasValues.setSasIpRange(sasIpRange); String containerSasToken = blobContainerClient.generateSas(serviceSasValues); System.out.println("\nGenerate the Container sas & url is :::: \n\t" + containerSasToken + "\n\t" + blobContainerClient.getBlobContainerUrl() + "?" + containerSasToken); // Generate a sas using a blob client BlobSasPermission blobSasPermission = new BlobSasPermission().setReadPermission(true); serviceSasValues = new BlobServiceSasSignatureValues(expiryTime, blobSasPermission); serviceSasValues.setStartTime(startTime); serviceSasValues.setProtocol(protocol); serviceSasValues.setSasIpRange(sasIpRange); String blobSasToken = blobClient.generateSas(serviceSasValues); System.out.println("\nGenerate the Blob sas & url is :::: \n\t" + blobSasToken + "\n\t" + blobClient.getBlobUrl() + "?" + blobSasToken); } }
參考資料
快速入門:使用 Java v12 SDK 管理 blob:https://docs.azure.cn/zh-cn/storage/blobs/storage-quickstart-blobs-java
Azure Storage Blob client library for Java:https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/storage/azure-storage-blob#generate-a-sas-token
示例下載:demo.rar