天父的儿女,甄情达,湖北医学院药护学院
使用 PHP 创建 COS 接口所需要的请求签名,按照官方示例,请求签名应用在需要身份校验的场景,即非公有读权限时。否则在请求API接口时,就必须携带签名作为请求头的一部分传递。
PUT /textfile HTTP1.1
,意思是将新上传的文件放在目标存储桶根目录下并命名为textfile
创建参数
先看一个官方文档给出的栗子
通过 RESTful API 对 COS 发起的 HTTP 签名请求,使用标准的 HTTP Authorization 头部来传递,如下例所示:
PUT /testfile2 HTTP/1.1 Host: bucket1-1254000000.cos.ap-beijing.myqcloud.com x-cos-content-sha1: 7b502c3a1f48c8609ae212cdfb639dee39673f5e x-cos-storage-class: standard Hello world
解读一下,这是一个很简单的http
请求,第一行是请求行,第二、三、四行都是请求头,先放在这儿,后面会用到。按照官方文档,先准备好必需的参数,参数均已键值对方式存在,首先看看官方给出的完整签名结构
q-sign-algorithm=sha1&q-ak=[SecretID]&q-sign-time=[SignTime]& q-key-time=[KeyTime]&q-header-list=[SignedHeaderList]& q-url-param-list=[SignedParameterList]&q-signature=[Signature]
文本中每一个方括号中的内容就是用户信息,其实sha1
也是一个参数截止到发文官方文档表示只支持sha1
因此直接填写即可,其它的以下逐一解读
键
,固定值,接口设定AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q
HTTP Request Headers
。往回倒两步来看2. 创建参数
开始时给出的请求示例。Host
、x-cos-content-sha1
、x-cos-storage-class
说明该请求全部请求头有三个,因此[SignedHeaderList]
可以有这三个请求头组成,也可以挑两个甚至一个(我按照理论猜测未测试)。该值是由请求头的Key部分组成,Key需转化为小写并且以字典排序再用连接符;
连接,正确处理后的结果应该是host;x-cos-content-sha1;x-cos-storage-class
。当然如果有Content-Type
这样的请求头,结果应为content-type;host;x-cos-content-sha1;x-cos-storage-class
。HTTP
请求部分,即第一行请求行。官方给出的例子是HTTP请求GET /?prefix=abc&max-keys=20
时,[SignedParameterList]
为max-keys;prefix
或prefix
。按字面意思如果是非GET请求应该就没有查询部分也就没有参数,该值应该是空。根据上面的结构分解,可以了解到以下结构
[Signature]
需要进一步计算Host
,因为原始请求头将作为一种数据源影响请求签名的计算结果了解了结构之后,开始创建一个签名,为了和官方文档比对结果,用户信息使用官方文档给出的内容
根据用户信息,带入到请求签名结构中,对应关系如下
键(key) | 值(value) | 备注 |
---|---|---|
q-sign-algorithm | sha1 | 目前仅支持 sha1 签名算法 |
q-ak | AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q | SecretId 字段 |
q-sign-time | 1417773892;1417853898 | 2014/12/5 18:04:52 到 2014/12/6 16:18:18 |
q-key-time | 1417773892;1417853898 | 2014/12/5 18:04:52 到 2014/12/6 16:18:18 |
q-header-list | host;x-cos-content-sha1;x-cos-storage-class | HTTP 头部 key 的字典顺序排序列表 |
q-url-param-list | HTTP 参数列表为空 | |
q-signature | 14e6ebd7955b0c6da532151bf97045e2c5a64e10 | 通过代码计算所得 |
以上是官方文档给出的“结果”,也就是说如果自己计算出来的7个键值对跟表格中结果一致,即说明算法正确。
/** * 计算签名 * secretId、secretKey 为必需参数,qSignStart、qSignEnd为调试需要,测试通过后应取消,改为方法内自动创建 */ function get_authorization( $secretId, $secretKey, $qSignStart, $qSignEnd, $fileUri, $headers ){ /* * 计算COS签名 * 2018-05-17 * author:cinlap <cash216@163> * ref:https://cloud.tencent.com/document/product/436/7778 */ $qSignTime = "$qSignStart;$qSignEnd"; //unix_timestamp;unix_timestamp $qKeyTime = $qSignTime; $header_list = get_q_header_list($headers); //如果 Uri 中带有 ?的请求参数,该处应为数组排序后的字符串组合 $url_param_list = ''; //compute signature $httpMethod = 'put'; $httpUri = $fileUri; //与 q-url-param-list 相同 $httpParameters = $url_param_list; //将自定义请求头分解为 & 连接的字符串 $headerString = get_http_header_string( $headers ); // 计算签名中的 signature 部分 $signTime = $qSignTime; $signKey = hash_hmac('sha1', $signTime, $secretKey); $httpString = "$httpMethod\n$httpUri\n$httpParameters\n$headerString\n"; $sha1edHttpString = sha1($httpString); $stringToSign = "sha1\n$signTime\n$sha1edHttpString\n"; $signature = hash_hmac('sha1', $stringToSign, $signKey); //组合结果 $authorization = "q-sign-algorithm=sha1&q-ak=$secretId&q-sign-time=$qSignTime&q-key-time=$qKeyTime&q-header-list=$header_list&q-url-param-list=$url_param_list&q-signature=$signature"; return $authorization; }
为了测试,该方法参数应该是多过需要了,前六个参数是已经给出的,是来自用户的,因此直接赋值即可
$authorization = "q-sign-algorithm=sha1&q-ak=$secretId&q-sign-time=$qSignTime&q-key-time=$qKeyTime...
从HTTP请求头中,选择全部或部分,将每项的key转化为小写并按字典排序,最终输出成字符串,多个key用字符 ; 连接
。代码如下*/
function get_q_header_list($headers){
if(!is_array($headers)){
return false;
}
try{
$tmpArray = array();
foreach( $headers as $key=>$value){
array_push($tmpArray, strtolower($key));
}
sort($tmpArray);
return implode(';', $tmpArray);
}
catch(Exception $error){
return false;
}
}
本例中,HTTP请求头是三个,因此输出结果应该是
host;x-cos-content-sha1;x-cos-storage-class```,和官方给出结果一致。
上面讲过,这个值是HTTP请求参数,对于PUT方法没有?后参数,自然值为0,所以代码中“偷懒”直接给了空字符串,实际应该根据用户给的URI做个智能判断之类的,但是想想从逻辑上不做也行。
算法官方已经给出了,PHP还是很幸福的直接拿来用,先看一下 $httpString
的组成。由四个部分组成 $httpMethod
、 $httpUri
、 $httpParameters
、 $headerString
。
/testfile
说明在存储桶根目录下创建一个叫 testfile
的文件,/image/face1.jpg
说明在根目录/image目录下建立一个叫 face1.jpg
的文件,至于是不是图片文件,不管根据请求头,选择全部或部分请求头,把每项的key都转换为小写,把value都进行URLEncode转换,每项格式都改为key=value,然后按照key进行字典排序,最后把它们用连接符 & 组成字符串
。这是我整理的逻辑,代码如下*/
function get_http_header_string($headers){
if(!is_array($headers)){
return false;
}
至此,请求签名中7个值都有了,有的是来自用户信息,有的需要计算,需要计算的上面也给出了所有的计算方法和为什么如此计算的个人理解。最后只需要按照官方要求进行输出即可。看一下
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例
YII2框架中ActiveDataProvider与GridView的配合使用操作示例
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
网友评论