使用 php 的 Azure 共享访问签名错误



我正在使用 SAS 尝试使用 php 从专用 Azure 存储容器下载 blob。但它总是给我带来同样的错误。

<Error>
<Code>AuthenticationFailed</Code>
<Message>
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. ...
</Message>
<AuthenticationErrorDetail>
Signature did not match. String to sign used ... /blob/name/container/archive.jpg
</AuthenticationErrorDetail>
</Error>

这是我的代码:

static private function getSASForBlob($accountName,$containerName, $fileName, $resourceType, $permissions, $expiry) {
     /* Create the signature */         
        $_arraysign = array();
        $_arraysign[] = $permissions;
        $_arraysign[] = '';
        $_arraysign[] = $expiry;
        $_arraysign[] = $accountName . '/' . $containerName . '/' . $fileName;
        $_arraysign[] = '';
        $_arraysign[] = "2015-04-05"; //the API version is now required
        $_arraysign[] = '';
        $_arraysign[] = '';
        $_arraysign[] = '';
        $_arraysign[] = '';
        $_arraysign[] = '';
        $_str2sign = implode("n", $_arraysign);
        return base64_encode(
        hash_hmac('sha256', urldecode(utf8_encode($_str2sign)), base64_decode($key), true)
    );
    }
    static public function getBlobDownloadUrl($container,$blob,$accountName,$key){
 /* Create the signed query part */         
        $resourceType='b';
        $permissions='r';
        /*$expTime_utc = new DateTime(null, new DateTimeZone("UTC"));
        $expTime_utc->add(new DateInterval('PT1H'));
        $expiry=$expTime_utc->format('Y-m-dTH:i:sZ');*/
        $expiry = date('Y-m-dTH:i:sZ', strtotime('+1 day'));
        $_signature=AzureServices::getSASForBlob($accountName,$key,$container, $blob, $resourceType, $permissions, $expiry);
        $_parts = array();
        $_parts[] = (!empty($expiry))?'se=' . urlencode($expiry):'';
        $_parts[] = 'sr=' . $resourceType;
        $_parts[] = (!empty($permissions))?'sp=' . $permissions:'';
        $_parts[] = 'sig=' . urlencode($_signature);
        $_parts[] = "sv=2015-04-05";
        /* Create the signed blob URL */
        $_url = 'https://'
        .$accountName.'.blob.core.windows.net/'
        . $container . '/'
        . $blob . '?'
        . implode('&', $_parts);
        return $_url;
    }

我尝试按照相同的结构将日期更改为日期时间,在"$_arraysign[] = $accountName"行中添加和删除"/"。/' .$containerName .'/' .$fileName" ...但是什么也没发生,显示相同的错误消息...请帮助我。谢谢

由于您在 2015-04-05 中使用signedversion,所以除了 Mantri 的答案之外@Gaurav还有一点您需要注意,那就是,根据 https://msdn.microsoft.com/en-us/library/azure/dn140255.aspx 中构造签名字符串一节中的描述:

版本 2015-04-05 添加了对签名 IP 和签名协议字段的支持。这些必须包含在字符串到签名中。若要为 Blob 或文件服务资源构造字符串到签名,请使用以下格式:

StringToSign = signedpermissions + "n" +
           signedstart + "n" +
           signedexpiry + "n" +
           canonicalizedresource + "n" +
           signedidentifier + "n" +
           signedIP + "n" +
           signedProtocol + "n" +
           signedversion + "n" +
           rscc + "n" +
           rscd + "n" +
           rsce + "n" +
           rscl + "n" +
           rsct

因此,我们需要将函数getSASForBlob中的$_arraysign修改为如下所示的内容:

$_arraysign = array();
$_arraysign[] = $permissions;
$_arraysign[] = '';
$_arraysign[] = $expiry;
$_arraysign[] = '/blob/' . $accountName . '/' . $container . '/' . $blob;
$_arraysign[] = '';
$_arraysign[] = '';
$_arraysign[] = '';
$_arraysign[] = "2015-04-05"; //the API version is now required
$_arraysign[] = '';
$_arraysign[] = '';
$_arraysign[] = '';
$_arraysign[] = '';
$_arraysign[] = '';

如有任何进一步的问题,请随时告诉我。

请在以下代码行中加上/blob/

$_arraysign[] = $accountName . '/' . $containerName . '/' . $fileName;

所以,它应该是:

$_arraysign[] = '/blob/' . $accountName .'/' .$containerName .'/' .$fileName;

从此页面: https://msdn.microsoft.com/en-us/library/azure/dn140255.aspx

字符串的规范化资源部分是指向 已签名的资源。它必须包含服务名称(Blob、表、 队列或文件)对于版本 2015-02-21 或更高版本,存储帐户 名称和资源名称,并且必须进行 URL 解码。目录的名称 必须包含 Blob 的容器。表名必须为小写。这 以下示例演示如何构造规范化资源 部分,具体取决于资源类型。

相关内容

最新更新