【问题标题】:Unable To Set Blob Service Properties无法设置 Blob 服务属性
【发布时间】:2021-05-09 22:36:24
【问题描述】:

我有一个问题,Azure 存储 Blob 没有返回 206 Partial content for video files。

问题: 视频已完全下载(300mb 视频需要 20-40 秒)并且搜索栏无法正常工作。我正在使用 Laravel,仅当我尝试从 Azure Blob 存储中检索 .mp4 文件时才会出现此问题。当我将媒体文件存储在公共磁盘上时,它工作正常。

一位微软员工表示,将 x-ms-version 更改为 2011-01-18 或更高版本将解决我的问题。 LINK参与讨论:

微软有一篇关于设置 blob 服务属性的帖子:HERE

注意他们实现这一目标的示例:https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-service-properties#sample-request-and-response

我正在尝试像这样通过 Postman 发送请求:

PUT https://{account-name}.blob.core.windows.net/?restype=service&comp=properties

Postman 中包含的标头和响应:

我搜索了错误并在 SO 上找到了这个问题: The MAC signature found in the HTTP request '...' is not the same as any computed signature

它有一个公认的答案,但我似乎不明白。我的请求/授权标头有问题吗?还是我需要采取不同的方法?

提前致谢!

我在 LARAVEL 中的代码:

 $date = gmdate('D, d M Y H:i:s \G\M\T');
    $account_name = "xyz";
    $containername = "media";
    $account_key = "access_key";

    $canonicalizedHeaders  = "x-ms-date:$date\nx-ms-version:2017-11-09";
    $canonicalizedResource = "/$account_name/$containername\ncomp:list\nrestype:container";

    $arraysign = array();
    $arraysign[] = 'GET';                     /*HTTP Verb*/
    $arraysign[] = '';                        /*Content-Encoding*/
    $arraysign[] = '';                        /*Content-Language*/
    $arraysign[] = '';                        /*Content-Length (include value when zero)*/
    $arraysign[] = '';                        /*Content-MD5*/
    $arraysign[] = '';                        /*Content-Type*/
    $arraysign[] = '';                        /*Date*/
    $arraysign[] = '';                        /*If-Modified-Since */
    $arraysign[] = '';                        /*If-Match*/
    $arraysign[] = '';                        /*If-None-Match*/
    $arraysign[] = '';                        /*If-Unmodified-Since*/
    $arraysign[] = '';                        /*Range*/
    $arraysign[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
    $arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

    $stringtosign = implode("\n", $arraysign);

    $signature = 'SharedKey' . ' ' . $account_name . ':' . base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($account_key), true));

    $endpoint = 'https://' . $account_name . '.blob.core.windows.net';
    $url = $endpoint . '/' . $containername . '?restype=container';

    $headers = [
        "x-ms-date:{$date}",
        'x-ms-version:2017-11-09',
        'Accept:application/json;odata=nometadata',
        "Authorization:{$signature}"
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response  = curl_exec($ch);
    echo curl_error($ch);
    curl_close($ch);
    echo '<pre>';
    print_r($response);

【问题讨论】:

  • 你把存储密钥作为共享密钥放在请求头中了吗?
  • 嗨@BowmanZhu,我正在使用来自门户的访问密钥。我不确定访问密钥是否等同于“存储”密钥?另外,有没有办法在邮递员中实现这一点?
  • REST API 不应该使用这个。 'SharedKey:' 之后的值是来自标头和存储密钥的签名(这只能从代码中生成)。仅仅使用postman是无法得到这个值的,需要使用代码生成,然后粘贴到'SharedKey'之后。
  • 生成很麻烦,而且每个REST API都不一样,我可以帮你找到相关的东西(如果你需要的话)。 :)
  • 那会很有帮助。我是否需要 Azure 门户中访问密钥的密钥和连接字符串?

标签: azure api postman azure-storage azure-blob-storage


【解决方案1】:

我可以在使用共享密钥时重现您的错误(此问题来自您提供存储帐户密钥而不是 HMAC 签名后的密钥。):

但是如果我使用AD不记名令牌,那么就没有问题了:

获取不记名令牌的 Python 代码:

import requests
from azure.identity import ClientSecretCredential 

client_id = 'xxx'
tenant_id = 'xxx'
client_secret = 'xxx'

credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
accesstoken = str(credential.get_token('https://yourstoragename.blob.core.windows.net/.default'))[19:1282]
print(str(credential.get_token('https://yourstoragename.blob.core.windows.net/.default')))

【讨论】:

    【解决方案2】:

    我建议您应该使用SAS token 而不是shared key 进行身份验证。 SAS 令牌易于生成和管理。

    以下是使用 SAS 令牌设置 blob 服务属性的步骤:

    1.导航到Azure门户->您的存储帐户->设置->共享访问签名:根据需要选择适当的选项->然后单击“生成SAS和连接字符串”按钮->最后,在生成SAS token,将其复制并保存在某些编辑器中,例如.txt 文件。截图如下:

    2.使用 SAS 令牌构建 url。例如,请求 url 是https://xx.blob.core.windows.net/?restype=service&amp;comp=properties,那么将 SAS 令牌放在请求 url 的末尾。 注意:您应该删除第一个“?”从 SAS 令牌开始,并在 SAS 令牌的开头放置一个“&”。

    如果 SAS 令牌是 ?sv=2020-02-10&amp;ss=b&amp;srt=sco&amp;sp=rwdlacx&amp;se=2021-02-25T10:44:44Z&amp;st=2021-02-25T02:44:44Z&amp;spr=https&amp;sig=xx

    那么request url with SAS 令牌应该如下所示:

    https://xx.blob.core.windows.net/?restype=service&comp=properties&sv=2020-02-10&ss=b&srt=sco&sp=rwdlacx&se=2021-02-25T10:44:44Z&st=2021-02-25T02:44:44Z&spr=https&sig=xxx
    

    3.在postman中,使用request url with SAS token作为请求url,在Headers选项卡中,只需填写x-ms-datex-ms-version这2个headers。由于我们使用 SAS 令牌,因此无需使用 Authorization 标头。这是截图:

    4.在正文选项卡中,按照Request Body doc 编写正确的请求正文。由于我使用的是x-ms-version == 2020-04-08,所以我按照the doc中的“对于版本2019-12-12或更高版本,请求正文的格式如下:”。截图如下(我只是修改了软删除属性,以及它的保留期限):

    5.运行测试后,在postman中,我可以看到响应码是202。在azure portal中,soft-delete属性开启,保留期也设置正确:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2015-02-08
      相关资源
      最近更新 更多