使用Microsoft.WindowsAzure.Storage创建共享访问令牌返回403
我有一个相当简单的方法,使用新的存储API创建SAS并将blob从一个容器复制到另一个容器 我正试图使用它在存储帐户之间复制blob。因此,我有两个存储帐户,使用完全相同的容器,我正在尝试将blob从存储帐户的容器复制到另一个存储帐户的容器 我不知道SDK是否是为此而构建的,但这似乎是一个常见的场景 一些补充资料:使用Microsoft.WindowsAzure.Storage创建共享访问令牌返回403,azure,azure-storage,azure-storage-blobs,Azure,Azure Storage,Azure Storage Blobs,我有一个相当简单的方法,使用新的存储API创建SAS并将blob从一个容器复制到另一个容器 我正试图使用它在存储帐户之间复制blob。因此,我有两个存储帐户,使用完全相同的容器,我正在尝试将blob从存储帐户的容器复制到另一个存储帐户的容器 我不知道SDK是否是为此而构建的,但这似乎是一个常见的场景 一些补充资料: 我在目标容器上创建令牌。 是否需要在源和目标上创建该令牌?注册令牌需要时间吗?我是否需要为每个请求创建它,或者每个令牌“生存期”只创建一次 我应该提到403是一个未经授权的结果htt
private static string CreateSharedAccessToken(CloudBlobClient blobClient, string containerName)
{
var container = blobClient.GetContainerReference(containerName);
var blobPermissions = new BlobContainerPermissions();
// The shared access policy provides read/write access to the container for 10 hours:
blobPermissions.SharedAccessPolicies.Add("SolutionPolicy", new SharedAccessBlobPolicy()
{
// To ensure SAS is valid immediately we don’t set start time
// so we can avoid failures caused by small clock differences:
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
Permissions = SharedAccessBlobPermissions.Write |
SharedAccessBlobPermissions.Read
});
blobPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(blobPermissions);
return container.GetSharedAccessSignature(new SharedAccessBlobPolicy(), "SolutionPolicy");
}
接下来,我使用此令牌调用复制操作,该操作返回403:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
destBlob.StartCopyFromBlob(uri);
我的Azure.Storage版本是2.1.0.2
以下是案例中的完整复制方法,有助于:
private static void CopyBlobs(
CloudBlobContainer srcContainer, string blobToken,
CloudBlobContainer destContainer)
{
var srcBlobList
= srcContainer.ListBlobs(string.Empty, true, BlobListingDetails.All); // set to none in prod (4perf)
//// get the SAS token to use for all blobs
//string token = srcContainer.GetSharedAccessSignature(
// new SharedAccessBlobPolicy(), "SolutionPolicy");
bool pendingCopy = true;
foreach (var src in srcBlobList)
{
var srcBlob = src as ICloudBlob;
// Determine BlobType:
ICloudBlob destBlob;
if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
{
destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
}
else
{
destBlob = destContainer.GetPageBlobReference(srcBlob.Name);
}
// Determine Copy State:
if (destBlob.CopyState != null)
{
switch (destBlob.CopyState.Status)
{
case CopyStatus.Failed:
log.Info(destBlob.CopyState);
break;
case CopyStatus.Aborted:
log.Info(destBlob.CopyState);
pendingCopy = true;
destBlob.StartCopyFromBlob(destBlob.CopyState.Source);
return;
case CopyStatus.Pending:
log.Info(destBlob.CopyState);
pendingCopy = true;
break;
}
}
// copy using only Policy ID:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
destBlob.StartCopyFromBlob(uri);
//// copy using src blob as SAS
//var source = new Uri(srcBlob.Uri.AbsoluteUri + token);
//destBlob.StartCopyFromBlob(source);
}
}
最后是账户和客户(审查)代码:
当我使用REST客户端时,这似乎有效。。。有什么想法吗 此任务不需要共享访问令牌。我有两个账户,效果很好:
var accountSrc = new CloudStorageAccount(credsSrc, true);
var accountDest = new CloudStorageAccount(credsSrc, true);
var blobClientSrc = accountSrc.CreateCloudBlobClient();
var blobClientDest = accountDest.CreateCloudBlobClient();
// Set permissions on the container.
var permissions = new BlobContainerPermissions {PublicAccess = BlobContainerPublicAccessType.Blob};
srcContainer.SetPermissions(permissions);
destContainer.SetPermissions(permissions);
//grab the blob
var sourceBlob = srcContainer.GetBlockBlobReference("FOO");
var destinationBlob = destContainer.GetBlockBlobReference("BAR");
//create a new blob
destinationBlob.StartCopyFromBlob(sourceBlob);
因为两个CloudStorageAccount对象都指向同一个帐户,所以不使用SAS令牌进行复制就可以了,正如您刚才提到的那样 另一方面,您需要一个可公开访问的blob或SAS令牌从另一个帐户进行复制。因此,您的尝试是正确的,但您建立了一个容器级访问策略,该策略最多需要30秒才能生效,如中所述。在此间隔期间,与存储的访问策略关联的SAS令牌将失败,状态代码403(禁止),直到访问策略变为活动状态
我想指出的另一点是;调用Get*BlobReference创建新的blob对象时,在执行Get/HEAD操作(如FetchAttributes)之前,不会填充CopyState属性。请考虑此问题:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
可能您正在调用Uri的“ToString”方法,该方法生成url的“可编辑”版本。如果blobToken包含特殊字符,例如“+”,这将在存储服务器上导致令牌格式错误,拒绝授予您访问权限
改用这个:
String uri = srcBlob.Uri.AbsoluteUri + blobToken;
从您创建SAS到使用URL进行复制之间有多长时间?它会立即发生;我调用了SAS方法,并在几秒钟后调用StartCopyFromBlob()api调用。这可能与uri编码有关吗?我曾看到报告称REST客户端可以工作,但Azure SDK失败,但没有找到解决方案。我刚刚意识到问题在于它是在两个不同的帐户之间运行的-我认为这意味着我需要两个帐户(目标和源)的信誉?我不确定SAS将如何跨blob内容服务器工作。如果您拥有这两个帐户,那么是的,您所做的一切都很好。我对SAS的猜测是时钟漂移。创建SAS时,您给了它一个过期时间,但没有给它一个开始时间,这意味着它立即启动。服务器上的时钟可能会相互偏移一点,这意味着SAS可能无法立即工作。答案是在过去几分钟内创建具有启动时间的SAS。
String uri = srcBlob.Uri.AbsoluteUri + blobToken;