【问题标题】:Azure - call Storage rest api for list blobsAzure - 为列表 blob 调用 Storage rest api
【发布时间】:2013-09-04 20:19:54
【问题描述】:

我要做的是连接到 Azure Storage Rest API List Blob。参考:http://msdn.microsoft.com/en-us/library/windowsazure/dd135734.aspx

我曾尝试关注http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx 以指定授权标头,但我收到 403 错误 - 禁止。

代码:

Uri address = new Uri("https://account.blob.core.windows.net/$logs?restype=container&comp=list");
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
req.Headers["x-ms-date"] = "2013-09-04";
req.Headers["x-ms-version"] = "2012-02-12";
req.Method = "GET";

string StringToSign =  "GET\n"
    + "\n" // content encoding
    + "\n" // content language
    + "\n" // content length
    + "\n" // content md5
    + "\n" // content type
    + "\n" // date
    + "\n" // if modified since
    + "\n" // if match
    + "\n" // if none match
    + "\n" // if unmodified since
    + "\n" // range
    + "x-ms-date: 2013-09-04\nx-ms-version:2012-02-12\n" // headers
    + "/account/blob\ncomp:list\nrestype:container"; // resources

string accountName = "account";
string key = Convert.ToBase64String(Encoding.Default.GetBytes(StringToSign));
req.Headers["Authorization"] = string.Format("SharedKey {0}:{1}", accountName, key);

HttpWebResponse resp = req.GetResponse() as HttpWebResponse;

任何人都可以看到任何错误吗?有没有可以生成密钥的工具?我不确定的一件事是我正在正确编码/散列字符串。

谢谢, 安德鲁

使用最新代码更新。这段代码给了我一个禁止错误。

DateTime dt = DateTime.UtcNow;
string StringToSign = "GET\n"
    + "\n" // content encoding
    + "\n" // content language
    + "\n" // content length
    + "\n" // content md5
    + "\n" // content type
    + "\n" // date
    + "\n" // if modified since
    + "\n" // if match
    + "\n" // if none match
    + "\n" // if unmodified since
    + "\n" // range
    + "x-ms-date: " + dt.ToString("R") + "\nx-ms-version:2012-02-12\n" // headers
    + "/account/$logs\ncomp:list\nrestype:container";

string auth = SignThis(StringToSign, "accountkey", "account");
string method = "GET";
string urlPath = "https://account.blob.core.windows.net/$logs?restype=container&comp=list";
Uri uri = new Uri(urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.Headers.Add("x-ms-date", dt.ToString("R"));
request.Headers.Add("x-ms-version", "2012-02-12");
request.Headers.Add("Authorization", auth);

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
}

【问题讨论】:

  • 当你说“有没有可以生成密钥的工具”时,我很怀疑。您是从 azure 管理门户中的 azure 存储页面获取密钥吗?
  • 是的。我是 Azure 新手 - 我可以访问门户,我是否打算使用门户中列出的密钥?还是通过上面的代码构造密钥?
  • 我现在明白你在用“StringToSign”做什么了。这不是这个例子想要告诉你的。您给出的是结果,而不是要发送的值。让我试着做点什么。拖累的是我有所有这些代码在工作。
  • 您应该使用门户中的密钥。与您的帐户名一起的密钥是您的身份验证。这就是为什么您不能将这些密钥分享给所有人的原因。
  • 哪个键?订阅号?如果是这样,为什么 MSDN 上面的页面告诉你要完成所有这些步骤?不是拖钓,只是好奇。谢谢

标签: c# rest azure


【解决方案1】:

上面的代码有一些问题。但在此之前,您首先需要的是存储帐户的密钥。您可以从 Windows Azure 门户获取它。单击门户中的存储帐户名称,然后单击“管理访问密钥”,如下面的屏幕截图所示:

现在讨论问题:

您创建授权标头的方式不正确。要创建授权标头,您需要上面代码中的帐户名、帐户密钥和 StringToSign。试试这个代码:

private static String SignThis(String StringToSign, string Key, string Account)
        {
            String signature = string.Empty;
            byte[] unicodeKey = Convert.FromBase64String(Key);
            using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
            {
                Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
                signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
            }

            String authorizationHeader = String.Format(
                  CultureInfo.InvariantCulture,
                  "{0} {1}:{2}",
                  "SharedKey",
                  Account,
                  signature);

            return authorizationHeader;
        }

上面的函数将提供授权标头,您需要将其作为授权传递。

我注意到的第二件事是,在StringToSign 的代码中,您没有传递容器名称。所以你的StringToSign 应该是:

string StringToSign =  "GET\n"
    + "\n" // content encoding
    + "\n" // content language
    + "\n" // content length
    + "\n" // content md5
    + "\n" // content type
    + "\n" // date
    + "\n" // if modified since
    + "\n" // if match
    + "\n" // if none match
    + "\n" // if unmodified since
    + "\n" // range
    + "x-ms-date: 2013-09-04\nx-ms-version:2012-02-12\n" // headers
    + "/account/$logs\ncomp:list\nrestype:container"; // resources 

您提到您对 Windows Azure 很陌生。如果我可以建议的话 - 许多人之前也已经完成了 REST API 的实现。请看看他们做了什么,而不是再次尝试做同样的事情。您可能会发现这些链接很有用:

http://convective.wordpress.com/2010/08/18/examples-of-the-windows-azure-storage-services-rest-api/

http://azurestoragesamples.codeplex.com/ - 查看此项目中的 REST API 实现。

更新

这是工作代码(只需更改帐户名称、密钥和容器名称)

static void ListContainers()
{
    string Account = "account";
    string Key = "key";
    string Container = "$logs";
    DateTime dt = DateTime.UtcNow;
    string StringToSign = String.Format("GET\n"
        + "\n" // content encoding
        + "\n" // content language
        + "\n" // content length
        + "\n" // content md5
        + "\n" // content type
        + "\n" // date
        + "\n" // if modified since
        + "\n" // if match
        + "\n" // if none match
        + "\n" // if unmodified since
        + "\n" // range
        + "x-ms-date:" + dt.ToString("R") + "\nx-ms-version:2012-02-12\n" // headers
        + "/{0}/{1}\ncomp:list\nrestype:container", Account, Container);

    string auth = SignThis(StringToSign, Key, Account);
    string method = "GET";
    string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list", Account, Container);
    Uri uri = new Uri(urlPath);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = method;
    request.Headers.Add("x-ms-date", dt.ToString("R"));
    request.Headers.Add("x-ms-version", "2012-02-12");
    request.Headers.Add("Authorization", auth);

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
    }
}

希望这会有所帮助。

【讨论】:

  • 感谢您的详细回复。有几件事:在 SignThis 中,您引用了一个名为 canonicalizedString 的变量,我认为这应该是 StringToSign ?其次,什么是规范化字符串?第三,当我运行这段代码时,我仍然被禁止,并且每次执行时生成的密钥都不同,是吗?
  • 对不起......我的错......剪切/粘贴错误:P。是的,这应该是StringToSign。所以基本上StringToSign 是用于创建授权标头的规范化字符串。您是否可以使用更新后的代码更新您的原始帖子,以便我们确切知道发生了什么。
  • 添加了代码。在 StringToSign 变量中是否需要包含所有字段,即使我没有该字段的值?
  • 这是一个难以捕捉的错误 :)。基本上在以下代码中x-ms-date: 之后有一个空格:+ "x-ms-date: " + dt.ToString("R") + "\nx-ms-version:2012-02-12\n"。去掉空格,代码应该可以正常工作。我还用我写的代码更新了我的答案。
  • 谢谢!我很高兴能帮到你。是的,你是对的。您需要添加所有查询字符串参数。一件重要的事情是 querystring 参数必须按字母顺序排序。所以你的代码是:"/{0}/{1}\ncomp:list\ninclude=snapshots\nrestype:container。试试看。它应该工作。有关更多信息,请参阅此链接:msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx。向下滚动到标题为“构建规范化资源字符串”的部分。 HTH。
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 2020-03-12
  • 2017-06-09
  • 2013-09-21
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 2021-06-01
相关资源
最近更新 更多