Microsoft Azure and SAS for PHP


Microsoft Azure and SAS for PHP

i尝试使用PHP创建到blob资源的SAS链接。不幸的是,目前在azure SDK中没有创建SAS签名的方法。我写了一个生成SAS的代码,但当我试图通过这种方法生成的链接获取资源时,我得到了这样的消息:签名字段格式不正确

    public function getSharedAccessSignatureURL($container, $blob)
{
    $signedStart = date('c', strtotime('-1 day'));
    $signedExpiry = date('c', strtotime('+1 day'));
    $signedResource = 'b';
    $signedPermission = 'r';
    $signedIdentifier = '';
    $responseContent = "file; attachment";
    $responseType = "binary";
    $canonicalizedResource = '/'.$this->account['accountName'].'/'.$container.'/'.$blob;
    $signedVersion = '2014-02-14';
    $stringToSign =
        $signedPermission."'n".
        $signedStart."'n".
        $signedExpiry."'n".
        $canonicalizedResource."'n".
        $signedIdentifier."'n".
        $signedVersion;
    $signature = base64_encode(
        hash_hmac(
            'sha256',
            urldecode(utf8_encode($stringToSign)),
            $this->account['primaryKey'],
            true
        )
    );
    $arrayToUrl = [
        'sv='.urlencode($signedVersion),
        'st='.urlencode($signedStart),
        'se='.urlencode($signedExpiry),
        'sr='.urlencode($signedResource),
        'sp='.urlencode($signedPermission),
        'rscd='.urlencode($responseContent),
        'rsct='.urlencode($responseType),
        'sig='.urlencode($signature)
    ];
    $url =  'https://'.$this->account['accountName'].'.blob.core.windows.net'.'/'
        .$container.'/'
        .$blob.'?'.implode('&', $arrayToUrl);
    return $url;
}

有人认为我做错了什么吗?我是微软Azure 的新手

我认为您的$stringToSign变量有问题。基于此处的文档:http://msdn.microsoft.com/en-US/library/azure/dn140255.aspx,您要签名的字符串应该构造如下:

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

考虑到您在SAS查询字符串中包含rscdrsct。请尝试以下操作,看看是否有区别:

    $stringToSign =
            $signedPermission."'n".
            $signedStart."'n".
            $signedExpiry."'n".
            $canonicalizedResource."'n".
            $signedIdentifier."'n".
            $signedVersion."'n".
            "'n".
            $responseContent."'n".
            "'n".
            "'n".
            $responseType;

更新

请尝试下面的代码。将帐户名称/密钥、容器名称和blob名称替换为适当的值:

<?php
$signedStart = gmdate('Y-m-d'TH:i:s'Z', strtotime('-1 day'));
echo $signedStart."'n";
$signedExpiry = gmdate('Y-m-d'TH:i:s'Z', strtotime('+1 day'));
echo $signedExpiry."'n";
$signedResource = 'b';
$signedPermission = 'r';
$signedIdentifier = '';
$accountName = "[account name]";
$accountKey = "[account key]";
$container = "[container name]";
$blob = "[blob name]";
$canonicalizedResource = '/'.$accountName.'/'.$container.'/'.$blob;
$signedVersion = '2014-02-14';  
echo $canonicalizedResource."'n";
$rscc = '';
$rscd = 'file; attachment';//Content disposition
$rsce = '';
$rscl = '';
$rsct = 'binary';//Content type
$stringToSign = 
                $signedPermission."'n".
                $signedStart."'n".
                $signedExpiry."'n".
                $canonicalizedResource."'n".
                $signedIdentifier."'n".
                $signedVersion."'n".
                $rscc."'n".
                $rscd."'n".
                $rsce."'n".
                $rscl."'n".
                $rsct;

echo $stringToSign."'n";
$signature = base64_encode(
        hash_hmac(
            'sha256',
            $stringToSign,
            base64_decode($accountKey),
            true
        )
    );
echo $signature."'n";

$arrayToUrl = [
        'sv='.urlencode($signedVersion),
        'st='.urlencode($signedStart),
        'se='.urlencode($signedExpiry),
        'sr='.urlencode($signedResource),
        'sp='.urlencode($signedPermission),
        'rscd='.urlencode($rscd),
        'rsct='.urlencode($rsct),
        'sig='.urlencode($signature)
    ];
    $url =  'https://'.$accountName.'.blob.core.windows.net'.'/'
        .$container.'/'
        .$blob.'?'.implode('&', $arrayToUrl);
echo $url."'n";
?>

本质上有两个问题(除了不正确的$stringToSign变量):

  1. 开始/结束日期时间的格式不正确
  2. 我们需要base64_decode帐户密钥来计算签名

我遇到了完全相同的问题。但现在您可以使用MicrosoftAzure'Storage'Common'SharedAccessSignatureHelper,它可以为您处理许多问题。两年前,我在这份公关中被添加到了公共图书馆(https://github.com/Azure/azure-storage-php/pull/73/files)。

它应该像这样简单地解决:

$sasHelper = new SharedAccessSignatureHelper(
    'nameofyouraccount',
    'H...your-token...=='
);
$sas = $sasHelper->generateAccountSharedAccessSignatureToken(
    '2018-11-09',
    'rwl',
    'b',
    'sco',
    (new 'DateTime())->modify('+10 minute'),
    (new 'DateTime())->modify('-5 minute'),
    '',
    'https'
);
$connectionString = "BlobEndpoint=https://nameofyouraccount.blob.core.windows.net/;SharedAccessSignature={$sas}";

你得到了你的连接字符串!

修改并转入@Gaurav Mantri 的函数

function generateSasToken($bucket,$key, $accountName, $accountKey){
    $signedStart = gmdate('Y-m-d'TH:i:s'Z', time());
    $signedExpiry = gmdate('Y-m-d'TH:i:s'Z', time()+3600);
    $signedResource = 'b';
    $signedPermission = 'r';
    $signedIdentifier = '';
    $canonicalizedResource = '/' . $accountName . '/' . $bucket . '/' . $key;
    $signedVersion = '2014-02-14';
    $rscc = '';
    $rscd = 'file; attachment';//Content disposition
    $rsce = '';
    $rscl = '';
    $rsct = 'binary';//Content type
    $stringToSign =
        $signedPermission . "'n" .
        $signedStart . "'n" .
        $signedExpiry . "'n" .
        $canonicalizedResource . "'n" .
        $signedIdentifier . "'n" .
        $signedVersion . "'n" .
        $rscc . "'n" .
        $rscd . "'n" .
        $rsce . "'n" .
        $rscl . "'n" .
        $rsct;
    $signature = base64_encode(
        hash_hmac(
            'sha256',
            $stringToSign,
            base64_decode($accountKey),
            true
        )
    );
   $arrayToUrl = [
        'sv=' . urlencode($signedVersion),
        'st=' . urlencode($signedStart),
        'se=' . urlencode($signedExpiry),
        'sr=' . urlencode($signedResource),
        'sp=' . urlencode($signedPermission),
        'rscd=' . urlencode($rscd),
        'rsct=' . urlencode($rsct),
        'sig=' . urlencode($signature)
    ];
    $url = 'https://' . $accountName . '.blob.core.windows.net' . '/'
        . $bucket . '/'
        . $key . '?' . implode('&', $arrayToUrl);
    return $url;
}