适用于 PHP 的 Microsoft Azure 和 SAS
Posted
技术标签:
【中文标题】适用于 PHP 的 Microsoft Azure 和 SAS【英文标题】:Microsoft Azure and SAS for PHP 【发布时间】:2014-12-15 20:21:27 【问题描述】:我尝试使用 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;
任何建议我做错了什么?我是 Microsoft Azure 的新手
【问题讨论】:
你是先用谷歌搜索的吗? social.msdn.microsoft.com/Forums/en-US/… 。只是好奇- 是的。但是对于PHP来说并没有太多。我真的不明白,尤其是我尝试遵循文档。 msdn.microsoft.com/en-US/library/azure/dn140255.aspx有经验的有什么建议吗? 【参考方案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
考虑到您在 SAS 查询字符串中包含 rscd
和 rsct
。请尝试以下方法,看看是否有所不同:
$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
计算签名的帐户密钥。
【讨论】:
“签名字段格式不正确”仍然没有区别。我不需要 rscd、rsct 参数,如果它改变了 stringTosign 中的任何内容? 你能打印你的 $stringToSign 变量吗? 我要签名的字符串:r\n2014-10-20T12:34:40+02:00\n2014-10-22T12:34:40+02:00\n/accountname/new/invoice .pdf\n\n2014-02-14\n\n文件;附件\n\n\n二进制 更新了我的答案。 HTH。 感谢您的帮助。问题出在日期格式上。问候:)【参考方案2】:我遇到了完全相同的问题。但是现在您可以使用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";
你得到了你的连接字符串!
【讨论】:
要获取 blob 特定的 SAS URL,请转到 azure.github.io/azure-storage-php 并搜索 (Ctrl
+ F
) 以查找 BlobSharedAccessSignatureHelper
以查看类方法。它与@yustme 所拥有的非常相似。【参考方案3】:
从@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;
【讨论】:
以上是关于适用于 PHP 的 Microsoft Azure 和 SAS的主要内容,如果未能解决你的问题,请参考以下文章
适用于 Cordova 的 Azure 移动服务/VS 工具 - 404
如何确定 Azure Defender 适用于哪些 blob?
适用于 .NET Core Azure WebJob 的 Application Insights
如何从适用于 Node.js 的 Azure blob v12 SDK 中删除 blob
适用于 blob 的 Azure Java SDK - 已请求加载默认 HttpClient 提供程序,但在类路径中找不到该提供程序