我想將 blob 從一個存盤帳戶 (ADLS Gen2) 復制到另一個存盤帳戶(相同型別)。我什至有 SAS 令牌授權的作業代碼:
import com.microsoft.azure.storage.{CloudStorageAccount,StorageException,StorageCredentials,StorageCredentialsToken}
import com.microsoft.azure.storage.blob.{CloudBlobClient,CloudBlockBlob,CloudBlobDirectory,CloudBlobContainer,ListBlobItem}
val srcStorageAccountName = "<src-account-name>"
val destStorageAccountName = "<dest-account-name>"
// SAS authorization
val srcSas = "<src-sas-token>"
val srcCloudStorageAccount= CloudStorageAccount.parse(s"DefaultEndpointsProtocol=https;AccountName=${srcStorageAccountName};SharedAccessSignature=${srcSas};EndpointSuffix=core.windows.net")
val destSas = "<dest-sas-token>"
val destCloudStorageAccount= CloudStorageAccount.parse(s"DefaultEndpointsProtocol=https;AccountName=${destStorageAccountName};SharedAccessSignature=${destSas};EndpointSuffix=core.windows.net")
val destBlobClient = destCloudStorageAccount.createCloudBlobClient()
val srcBlobClient = srcCloudStorageAccount.createCloudBlobClient()
try {
val srcPath = "<src-path>"
val destPath = "<dest-path>"
val srcContainerName = "<src-container>"
val destContainerName = "<dest-container>"
val srcContainer = srcBlobClient.getContainerReference(srcContainerName)
val destContainer = destBlobClient.getContainerReference(destContainerName)
val blobs = srcContainer.listBlobs(srcPath)
import scala.jdk.CollectionConverters._
copyBlobList(blobs.asScala, destContainer, srcContainer, srcContainerName, srcPath, destPath)
} catch {
case e: StorageException =>
e.printStackTrace()
}
def copyBlobList(blobs: Iterable[ListBlobItem], destContainer: CloudBlobContainer, srcContainer: CloudBlobContainer, srcContainerName: String, srcPath: String, destPath: String): Unit = {
for (blob <- blobs) {
blob match {
case blockBlob: CloudBlockBlob => copySingleBlob(blockBlob, destContainer, srcContainer, srcContainerName, srcPath, destPath)
case blobDirectory: CloudBlobDirectory => copyBlobDirectory(blobDirectory, destContainer, srcContainer, srcContainerName, srcPath, destPath)
case _ => println(s"Unknown blob type")
}
}
}
def copySingleBlob(blob: CloudBlockBlob, destContainer: CloudBlobContainer, srcContainer: CloudBlobContainer, srcContainerName: String, srcPath: String, destPath: String): Unit = {
val srcBlob = srcContainer.getBlockBlobReference(blob.getUri.getPath.replaceFirst(srcContainerName, "").substring(1).replace(srcPath, destPath))
val destBlob = destContainer.getBlockBlobReference(blob.getUri.getPath.replaceFirst(srcContainerName, "").substring(1).replace(srcPath, destPath))
destBlob.startCopy(srcBlob)
}
def copyBlobDirectory(blobDirectory: CloudBlobDirectory, destContainer: CloudBlobContainer, srcContainer: CloudBlobContainer, srcContainerName: String, srcPath: String, destPath: String): Unit = {
val blobsFromDir = srcContainer.listBlobs(blobDirectory.getUri.getPath.replace(srcContainerName, ""))
import scala.jdk.CollectionConverters._
copyBlobList(blobsFromDir.asScala, destContainer, srcContainer, srcContainerName, srcPath, destPath)
}
這里的問題是任何其他授權都會導致例外: com.microsoft.azure.storage.StorageException:此存盤帳戶不允許公共訪問。
我努力了:
// Account key authorization
val destKey = "<dest-account-key>"
val srcKey = "<src-account-key>"
val srcCloudStorageAccount = CloudStorageAccount.parse(s"DefaultEndpointsProtocol=https;AccountName=${srcStorageAccountName};AccountKey=${srcKey};EndpointSuffix=core.windows.net")
val destCloudStorageAccount = CloudStorageAccount.parse(s"DefaultEndpointsProtocol=https;AccountName=${destStorageAccountName};AccountKey=${destKey};EndpointSuffix=core.windows.net")
// Access token authorization
val srcTokenCredentials = new StorageCredentialsToken(srcStorageAccountName, srcToken)
val srcCloudStorageAccount = new CloudStorageAccount(srcTokenCredentials, true)
val destTokenCredentials = new StorageCredentialsToken(destStorageAccountName, destToken)
val destCloudStorageAccount = new CloudStorageAccount(destTokenCredentials, true)
它們都允許在同一存盤帳戶內復制 blob,但在兩個不同存盤帳戶之間的復制操作失敗。
問題:我真正不明白的是為什么 SAS 授權允許在兩個存盤帳戶之間進行復制,而帳戶密鑰授權和訪問令牌授權失敗并出現此“不允許公共訪問”例外。有任何想法嗎?
謝謝
uj5u.com熱心網友回復:
- 默認情況下,存盤帳戶未配置為具有公共訪問權限。您可以從門戶、CLI、Powershell 或模板設定/檢查其值。如果您授予對存盤帳戶的公共訪問權限,則具有足夠權限的用戶可以訪問您的存盤帳戶。
- 但默認情況下,SAS 在生成它時被提供某些權限,例如讀/寫、服務、資源型別、開始和到期日期/時間、允許的 IP 地址等,從而可以訪問存盤帳戶的某些部分。
- 在您的情況下,您可能會提供訪問密鑰,但由于容器和 blob 的默認權限,您需要提供可由訪問密鑰生成的 SAS 令牌。
- 建議為客戶端提供 SAS,即提供用戶可以訪問所有存盤帳戶的訪問密鑰。而 SAS 為您提供了對您的存盤帳戶的受限訪問權限(僅在有限的時間內訪問您的存盤帳戶的一部分),并且如果您不想再通過輪換密鑰來授予訪問權限,也可以輕松地撤銷權限。
參考:
- 容器和 blob 的公共讀取訪問權限 - MSFT 檔案
- 使用 SAS 授予對 Azure 存盤資源的有限訪問權限 - MSFT 檔案
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/496946.html
下一篇:Scala反透視表
