用于复制blob操作问题的Azure SAS令牌

时间:2017-04-20 10:21:07

标签: php azure authentication azure-storage-blobs

我正在尝试将blob从一个存储帐户复制到另一个存储帐户,根据帖子here,我可以为shared access signature (SAS)生成x-ms-copy-source。现在我的问题是我无法通过复制blob操作的身份验证,它说“AuthenticationFailedServer failed to authenticate the request”。

我使用以下代码生成SAS令牌以及复制blob的身份验证签名。有人可以帮我解决问题吗

$date = gmdate('D, d M Y H:i:s \G\M\T');
$account_name = "souraccount";
$desaccname = "desaccount";
$destcontainername = "descontainer";
$blobname = "abc.png";
$sourcecontainer = "sourcecontainer";
$source_account_key = "asdfghjkl";
$destination_account_key = "poiuytr";

$expiry = gmdate("Y-m-d\TH:i:s\Z", time() + 30000);
$sig = getSASForBlob($account_name,$sourcecontainer, $blobname, "b", "r", $expiry, $source_account_key );
$url = getBlobUrl($account_name,$account_name,$blobname,"b","r",$expiry,$sig);

$canonicalizedHeaders = "x-ms-copy-source:".$url."\nx-ms-date:$date\nx-ms-version:2015-04-05";
$canonicalizedResource = "/$account_name/$sourcecontainer/$blobname";

$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[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
$arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

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

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

$endpoint = 'https://'.$desaccname.'.blob.core.windows.net';
echo $url = $endpoint.'/'.$destcontainername.'/'.$blobname;

$headers = [
    "x-ms-copy-source:$url",
    "x-ms-date:{$date}",
    "x-ms-version:2015-04-05",
    "Accept:application/json;odata=nometadata",
    "Accept-Charset:UTF-8",
    "Content-Length:0",
    "Authorization:{$signature}"
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
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);

function getSASForBlob($accountName,$container, $blob, $resourceType, $permissions, $expiry,$source_account_key ){
     /* Create the signature */
     $_arraysign = array();
     $_arraysign[] = $permissions;
     $_arraysign[] = '';
     $_arraysign[] = $expiry;
     $_arraysign[] = '/' . $accountName . '/' . $container . '/' . $blob;
     $_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($source_account_key ), true)
     );
}

 function getBlobUrl($accountName,$container,$blob,$resourceType,$permissions,$expiry,$_signature){
     /* Create the signed query part */
     $_parts = array();
     $_parts[] = 'sv=2015-04-05';
     $_parts[] = 'sr=' . $resourceType;
     $_parts[] = 'sig=' . urlencode($_signature);
     $_parts[] = (!empty($expiry))?'se=' . urlencode($expiry):'';    
     $_parts[] = (!empty($permissions))?'sp=' . $permissions:'';

     /* Create the signed blob URL */
     $_url = 'https://'
     .$accountName.'.blob.core.windows.net/'
     . $container . '/'
     . $blob . '?'
     . implode('&', $_parts);

     return $_url;
 }

2 个答案:

答案 0 :(得分:1)

@Gaurav Mantri在评论中写道:

  

我们肯定会取得一些进展:)。现在我相信您的SAS网址存在问题。请尝试更改以下行

$_arraysign[] = '/' . $accountName . '/' . $container . '/' . $blob;  
     

$_arraysign[] = '/blob/' . $accountName . '/' . $container . '/' . $blob; 
     

在你的getSASForBlob函数中。

答案 1 :(得分:0)

查找以下完整的工作代码,将blob从源存储帐户复制到目标存储帐户。 Gaurav Mantri 在评论部分给出的解决方案解决了我的问题

$date = gmdate('D, d M Y H:i:s \G\M\T');
$account_name = "saccname";  // Source Storage acoount name
$desaccname = "daccname";    // destination Storage acoount name 
$destcontainername = "vhd"; // destination Container name
$blobname = "sblob.vhd";    // source blob name
$sourcecontainer = "vhd";  // source container name
$source_account_key = "sdfsdfdsf";
$destination_account_key = "safdsf";

$expiry = gmdate("Y-m-d\TH:i:s\Z", time() + 30000);
$sig = getSASForBlob($account_name,$sourcecontainer, $blobname, "b", "r", $expiry, $source_account_key);
$xms_copy_source_url = getBlobUrl($account_name,$sourcecontainer,$blobname,"b","r",$expiry,$sig);

$canonicalizedHeaders = "x-ms-copy-source:".$xms_copy_source_url."\nx-ms-date:$date\nx-ms-version:2015-04-05";
$canonicalizedResource = "/$desaccname/$destcontainername/$blobname";

$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[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
$arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

$stringtosign = implode("\n", $arraysign);
$signature = 'SharedKey'.' '.$desaccname.':'.base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($destination_account_key), true));

$endpoint = 'https://'.$desaccname.'.blob.core.windows.net';
$url = $endpoint.'/'.$destcontainername.'/'.$blobname;

$headers = [
    "x-ms-copy-source:$xms_copy_source_url",
    "x-ms-date:{$date}",
    "x-ms-version:2015-04-05",
    "Accept:application/json;odata=nometadata",
    "Accept-Charset:UTF-8",
    'Content-Length:0'
    "Authorization:{$signature}"
];


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
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);


function getSASForBlob($accountName,$container, $blob, $resourceType, $permissions, $expiry,$source_account_key){
    /* Create the signature */
    $_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[] = '';

    $_str2sign = implode("\n", $_arraysign);

    return base64_encode(hash_hmac('sha256', urldecode(utf8_encode($_str2sign)), base64_decode($source_account_key), true));
}

 function getBlobUrl($accountName,$container,$blob,$resourceType,$permissions,$expiry,$_signature){ 
     /* Create the signed query part */
        $_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';
        $_parts[] = 'rscd=';

     /* Create the signed blob URL */
     $_url = 'https://'.$accountName.'.blob.core.windows.net/'. $container . '/'. $blob . '?'. implode('&', $_parts);

     return $_url;
 }