如何使用 PHP CURL 预请求代码创建容器 Azure 存储

How to create container azure storage using PHP CURL pre requested code

<?php
$accesskey = "{accesskey}";
$storageAccount = '{accountname}';
$destinationURL = "https://$storageAccount.blob.core.windows.net/{accountname}?restype=container";
function createContainer($storageAccount, $accesskey, $destinationURL)
{
    $currentDate = gmdate("D, d M Y H:i:s T", time());
    $headerResource = "x-ms-date:$currentDate\nx-ms-version:2015-12-11\nx-ms-default-encryption-scope:$accesskey\nx-ms-deny-encryption-scope-override:2015-12-11\nx-ms-meta-Name: StorageSample";
    $arraysign = array();
    $arraysign[] = 'PUT';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = 'application/json';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = '';
    $arraysign[] = $headerResource;
    $str2sign = implode("\n", $arraysign);
    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)) , base64_decode($accesskey) , true));
    $authHeader = "SharedKey $storageAccount:$sig";
    $headers = ['Authorization: ' . $authHeader, 'x-ms-date: ' . $currentDate, 'x-ms-version: 2015-12-11', 'Content-Type: application/json', 'x-ms-meta-Name: StorageSample', 'Content-Length:1024', 'x-ms-default-encryption-scope:' . $accesskey, 'x-ms-deny-encryption-scope-override: true'];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $destinationURL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
    $result = curl_exec($ch);
    echo "<pre>";
    print_r($result);
    echo curl_error($ch);
    curl_close($ch);
}
createContainer($storageAccount, $accesskey, $destinationURL);

?>

出现以下错误

AuthenticationFailedServer 未能验证请求。 确保授权值 header 的格式正确,包括签名。

如果要在我们创建 Azure blob 容器时使用请求 headers x-ms-default-encryption-scopex-ms-deny-encryption-scope-override,则 x-ms-version 应该晚于 2019-02- 02.

此外,我们创建共享密钥时,签名字符串的格式应该是这样的

StringToSign = VERB + "\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 + "\n" +  
               CanonicalizedHeaders +   
               CanonicalizedResource;  

但是您没有在代码中指定 CanonicalizedResource。请设置。

例如

$currentDate = gmdate("D, d M Y H:i:s T", time());
    $storageAccount="qsstorageacc";
    $containerName="mytest";
    $accesskey="";
    $encryptionScope="test";
    $currentDate = gmdate("D, d M Y H:i:s T", time());
    print $currentDate;
    print "\n";
    $headerResource = "x-ms-date:$currentDate\nx-ms-default-encryption-scope:$encryptionScope\nx-ms-deny-encryption-scope-override:true\nx-ms-meta-name:mytest\nx-ms-version:2020-04-08";
    $urlResource = "/$storageAccount/$containerName\nrestype:container";

    $arraysign = array();
    $arraysign[] = 'PUT';               /*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[] = $headerResource;     /*CanonicalizedHeaders*/
    $arraysign[] = $urlResource;        /*CanonicalizedResource*/

    $str2sign = implode("\n", $arraysign);
    print $str2sign;
    print "\n";

    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true));  
    $authHeader = "SharedKey $storageAccount:$sig";
    print $authHeader;
    print "\n";

    $headers = [
        'Authorization: ' . $authHeader,
        'x-ms-deny-encryption-scope-override: true',
        'x-ms-date: ' . $currentDate,
        'x-ms-default-encryption-scope: ' . $encryptionScope,
        'x-ms-version: 2020-04-08',
        'x-ms-meta-name: mytest',
        'Content-Length: 0'
    ];
    print_r($headers);
    $destinationURL="https://qsstorageacc.blob.core.windows.net/mytest?restype=container";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $destinationURL);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
    $result = curl_exec($ch);
    echo "<pre>";
    print_r($result);
    echo curl_error($ch);
    curl_close($ch);

详情请参考

https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key

https://docs.microsoft.com/en-us/rest/api/storageservices/create-container