Microsoft Azure и SAS для PHP
Я пытаюсь создать ссылку SAS на ресурс BLOB-объектов с помощью PHP. К сожалению, в настоящее время в 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;
}
Любой подсказать, что я делаю не так? Я новичок в Microsoft Azure
1 ответ
Я считаю, что есть проблема с вашим $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
учитывая, что вы в том числе rscd
а также rsct
в вашей строке запросов SAS. Пожалуйста, попробуйте следующее и посмотрите, имеет ли это значение:
$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
переменная):
- Дата начала / окончания не была правильно отформатирована.
- Нам нужно
base64_decode
ключ аккаунта для расчета подписи.
У меня точно такая же проблема. Но теперь вы можете использоватьMicrosoftAzure\Storage\Common\SharedAccessSignatureHelper
который может решить для вас множество проблем. Я был добавлен в общую библиотеку 2 года назад в этом PR (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;
}