Azure Blob 获取 Service SAS 爬坑
使用 zaure 对象存储,官方文档写的很详细 信任度很高但是还是掉坑里了,哎!记录一下为后人填坑吧。官方文档 https://docs.microsoft.com/en-us/rest/api/storageservices/create-account-sas
Service SAS
在使用azure blob (对象存储)的过程中 必然用到上传 和下载。上传文件功能在官方文档中写的很清楚,楼主在实现过程中并没有遇到什么坑, 例子如下 .各种语言也算覆盖的不错。今天主要搞一下 私有容器中共享访问签名的问题。
Azure 中共享访问签名(SAS)分为 Account SAS 和 Service SAS 。(楼主在这里搞错了 一开始用Account SAS 访问图片 不认真看文档的结果啊)
Account SAS 是用来访问服务的各种API 例如:设置Blob服务属性,获取Blob服务统计信息等。 Service SAS用来访问具体图片或者文件。
Create a service SAS
Service SAS 的构造方式 :
官方文档
在访问资源URl的后面以url param 的方式追加参数 例如 http://azuredata.net/data/demo.jpg?sv=2018-11-09&sig=MVas
其中 rc 和sig是参数名称。
参数在文档中描述的很详细 哪些必须传哪些非必传,每一个参数所代表的含义以及数据格式。
在这里简要阐述一下 详细内容可以看文档。
参数名称 | 必需或可选 | 描述 |
---|---|---|
sv | 需要 | 处理使用此共享访问签名发出的请求的服务版本。 |
sr | 需要 | 指定可以通过共享访问签名访问哪些Blob资源。 |
st | 可选的 | 共享访问签名变为有效的时间。UTC格式 |
se | 需要 | 共享访问签名变为失效的时间。UTC格式。 |
sp | 需要 | 指示拥有SAS的客户端可以对资源执行哪些操作。权限可以合并。r:读 |
sig | 需要 | 签名是使用SHA256算法在字符串到符号和密钥上计算的HMAC,然后使用Base64编码进行编码。 |
重点说一下sig :官方文档的描述是 The signature is an HMAC computed over the string-to-sign and key using the SHA256 algorithm, and then encoded using Base64 encoding.
我们先看一下官方给出的例子:Service SAS examples
我们直接看最新的格式 2013-08-15以后的
signedstart=2013-08-16
signedexpiry=2013-08-17
signedresource=c
signedpermissions=r
signedidentifier=YWJjZGVmZw==
signedversion=2013-08-15
responsecontent-disposition=file; attachment
responsecontent-type=binary
StringToSign = r + \n
2013-08-16 + \n
2013-08-17 + \n
/myaccount/pictures + \n
YWJjZGVmZw== + \n
2013-08-15 + \n
+ \n
file; attachment + \n
+ \n
+ \n
binary
HMAC-SHA256(URL.Decode(UTF8.Encode(StringToSign))) = a39+YozJhGp6miujGymjRpN8tsrQfLo9Z3i8IRyIpnQ=
(上面的signedpermissions指的是sp官方文档中都有描述其他。)
这里的StringToSign 指的就是上面文档中英文描述的 ‘string-to-sign’ , 也就是说 StringToSign的结构也可以理解出来 通过将不同的参数安回车拼接就可以得到 StringToSign。
第一个坑
这里需要注意的是 signedidentifier。 azure blob 中的访问策略密钥,blob容器中可选访问策略。但是并没有用到 因为你会发现他会提示 访问策略于SAS并不能同时使用。所以这个地方也算是个坑,signedidentifier可以等于“”空字符串 我们并不需要什么访问策略,我一开始以为它就是 ‘string-to-sign’ 坑了好久。
第二个坑
StringToSign拼接出来后,就是按照他给出的伪代码进行加密:
HMAC-SHA256(URL.Decode(UTF8.Encode(StringToSign))) 按字面上的理解 先进行 UTF8.Encode 然后 URL.Decode 之后进行 HMAC-SHA256 。但是HMAC-SHA256是需要密钥的,伪代码并没有告诉我们加密的密钥是什么,通过查看已经写好的轮子发现 源码是这样的
$decodedAccountKey = base64_decode($this->accountKey);
$signature = hash_hmac("sha256", $stringToSign, $decodedAccountKey, true);
$sig = urlencode(base64_encode($signature));
MD !!!不仅要用自己生成的KEY加密,还要base64一下再加密,之前有想到用key作为密钥但是没想到需要先base64一下,而且hash_hmac函数后面的这个true 代表需要转化成44位。默认是64位的加密串!!!
按照源码中的流程总算是可以了,但是最后还是选择调用已经写好的生成方法,楼主用是PHP
BlobSharedAccessSignatureHelper 的 generateBlobServiceSharedAccessSignatureToken方法。