0

我正在将 Windows Azure 从 1.7 迁移(叹气)到版本 2,我现在面临着旧身份验证方式的一些麻烦。当我尝试执行下一个代码时(使用 Azure SDK 的旧实现)......

[...]

var policy = new SharedAccessBlobPolicy();
policy.SharedAccessStartTime = new DateTimeOffset(DateTime.UtcNow.AddMinutes(-5));
policy.SharedAccessExpiryTime = policy.SharedAccessStartTime.Value.AddMinutes(5);
policy.Permissions = SharedAccessBlobPermissions.Read;

var sas = blobContainer.GetSharedAccessSignature(policy)
var request = WebRequest.Create(string.Format("{0}/{1}{2}", containerUri, blobName, sas));
request.Method = "GET";
var headers = new NameValueCollection();
headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add(headers);
request.ContentLength = 0;

var response = (HttpWebResponse)request.GetResponse();

[...]

... GetResponse() 方法对我很生气,并抛出一个 WebException 说“服务器无法验证请求。确保 Authorization 标头的值正确形成,包括签名。

ResponseUri 是http://127.0.0.1:10000/devstoreaccount1/testcontainer/testBlob?sv=2012-02-12&st=2013-01-22T09.52.27Z&se=2013-01-22T09.57.29Z&sr=c&sp=r&sig=WxFfIg9NxKodH7zGjKRym7RuXd61F5jlG6ILtG1UYPg%3D,对我来说看起来不错。我认为这是 AccountKey 的问题,但在真实存储上尝试使用 Azure 门户提供的正确密钥时,我遇到了同样的问题。

是否需要为新的 REST API 完成任何属性或新的初始化?

更新:我在他的回复中尝试了@Gaurav Mantri 开发的控制台应用程序,但它仍然不适合我。所以,我怀疑这个问题可能取决于我机器上的意大利语本地化,或者与 Windows 8 相关的一些东西(在另一位同事的机器上,控制台应用程序也不能正常工作,同样的错误 403,被禁止!由GetResponse)。我注意到我们得到的 URI 与我在网上找到的每个示例都不同,所以我将开始和到期时间视为(例如)2013-01-22T09.52.27Z而不是2013-01-22T09%3A52%3A27Z

4

3 回答 3

1

好的,我找到了问题所在。

将该行添加Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;到我的代码(或测试初始化​​程序)中将解决问题。

查看 WindowsAzure.Storage 源,当服务创建签名时,它使用格式字符串“yyyy-MM-ddTHH:mm:ssZ”,而不CultureInfo.InvariantCulture作为参数传递给ToString方法。但是对于意大利区域设置,小时、分钟和秒之间的分隔符是点,而美国是两点。所以我的本地机器和远程机器创建了两个不同的签名,它们无法匹配。

我将此报告为错误(或问题),因为并非每个人都有相同的区域设置。

于 2013-01-23T15:08:22.460 回答
0

对于 GET 操作,您不需要添加“x-ms-blob-type”请求标头。仅在上传 blob 时才需要。请在删除以下代码行后重试:

var headers = new NameValueCollection();
headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add(headers);

更新:这是使用 SAS URI 读取 blob 的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Net;
using System.IO;
namespace ConsoleApplication26
{
    class Program
    {
        static void Main(string[] args)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            CloudBlobContainer blobContainer = storageAccount.CreateCloudBlobClient().GetContainerReference("temp");
            //Create blob container.
            blobContainer.CreateIfNotExists();
            string blobContents = "Let's test SAS out :)";
            byte[] bytes = Encoding.UTF8.GetBytes(blobContents);

            string blobName = "sastest.txt";
            CloudBlockBlob blob = blobContainer.GetBlockBlobReference(blobName);
            //Upload blob
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                blob.UploadFromStream(ms);
            }
            //Get SAS Uri
            var sasUri = GetSasUrl(blobContainer, blobName);
            DownloadBlob(sasUri);

            Console.ReadLine();

        }

        static Uri GetSasUrl(CloudBlobContainer blobContainer, string blobName)
        {
            var policy = new SharedAccessBlobPolicy()
            {
                SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
                SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5),
                Permissions = SharedAccessBlobPermissions.Read,
            };

            var sas = blobContainer.GetSharedAccessSignature(policy);
            return new Uri(string.Format("{0}/{1}{2}", blobContainer.Uri, blobName, sas));
        }

        static void DownloadBlob(Uri sasUri)
        {
            var request = (HttpWebRequest)WebRequest.Create(sasUri);
            request.Method = "GET";
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                long responseContentLength = response.ContentLength;
                byte[] fetchedContents = new byte[(int) responseContentLength];
                using (var stream = response.GetResponseStream())
                {
                    stream.Read(fetchedContents, 0, fetchedContents.Length);
                }
                string blobContents = Encoding.UTF8.GetString(fetchedContents);
                Console.WriteLine("Blob Contents: " + blobContents);
            }
        }
    }
}
于 2013-01-22T11:56:58.640 回答
0

尝试上传文件时出现同样的错误。我进行了一些搜索,但建议的解决方案都没有奏效。

Then I checked the http response object in the inner exception and discovered that I had accidentally created the blob using not a filename but the full file path (c:\folder\folder\file.jpg instead of just file.jpb), so the url it was trying to upload to did not exist.

于 2014-01-02T05:02:12.077 回答