首頁  >  文章  >  後端開發  >  PHP產生騰訊雲COS介面所需的請求簽名

PHP產生騰訊雲COS介面所需的請求簽名

不言
不言原創
2018-06-01 11:22:271586瀏覽

這篇文章主要介紹了使用PHP 創建COS 接口所需要的請求簽名,與官方文檔給出的示例做比較,驗證算法的正確性,需要的朋友可以參考下

COS與請求簽章是什麼

COS 是騰訊雲物件儲存的縮寫及簡稱,請求簽章是第三方在呼叫COS相關介面時需要按需提供的、經過特定演算法建立而成的一組字串訊息,將唯一的標識當前第三方身份,提供通訊雙方的身份識別,只有有效的簽名COS才會提供服務

##目標

#使用PHP 建立COS 介面所需的請求簽名,與官方文件給出的範例做比較,驗證演算法的正確性

認識請求簽章##先來看一條官方文件給出的請求簽名的樣子

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]

請求簽名特點總結

    #是一串字串
  • key=value的鍵值對格式,key為固定值
  • 總共有7對key=value
  • sha1也是參數,但截止到官方發文只支援sha1,因此可以直接賦值
  • SignedHeaderList、SignedParameterList、Signature三個value需要透過演算法產生
  • #鍵值對的具體描述參見官方文件。

逐一擊破

請求簽名一共需要7個值,下面一一講解,各個擊破

q-sign-algorithm

簽名演算法,官方目前僅支援sha1,因此直接給值即可

q-ak

帳戶ID,即使用者的SecretId,可以在控制台 雲API金鑰 頁面取得

q-sign-time

目前簽章的有效起止時間,Unix時間戳記格式,英文半角分號 ; 分割,格式如 1480932292;1481012298

q-key-time

#與q-sign-time 值相同

q-header-list

個人理解,由HTTP請求頭組成,取全部或部分請求頭,將 key:value 形式的請求項目的key 部分取出,轉換小寫,多個key 按字典排序,以字元 ; 連接,最終組成字串

如原始請求頭有兩個:

Host:bucket1-1254000000.cos.ap-beijing.myqcloud.com
Content-Type:image/jpeg

key 就是Host 和Content-Type,經過運算後輸出 content-type;host

q-url-param-list

個人理解,由HTTP請求參數組成,取全部或部分請求參數,將 key =value 形式的請求參數的key 部分取出,轉換小寫,多個key 按字典排序,以字元 ; 連接,最終組成字串

如原始HTTP請求為:

GET /?prefix=abc&max-keys=20

key是prefix 和max-keys,經過運算後輸出 max-keys;prefix,如果請求沒有參數例如put、post,此處即為空

q-signature

根據HTTP內容計算簽名,演算法由COS提供,只需按要求給值

官方範例及參考結果

在開始編寫邏輯之前,先看一下官方範例給出的參考值,以及經過計算後的結果,以便和自己開發的邏輯進行結果比對

HTTP原始請求,也可以理解為計算簽名前或不需要簽名時的HTTP請求:

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請求:

PUT /testfile2 HTTP/1.1
Host: bucket1-1254000000.cos.ap-beijing.myqcloud.com
x-cos-content-sha1: 7b502c3a1f48c8609ae212cdfb639dee39673f5e
x-cos-storage-class: standard
Authorization: q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&> q-sign-time=1417773892;1417853898&q-key-time=1417773892;1417853898&q-header-list=host;x-cos-content-sha1;x-cos-storage-class&q-url-param-list=&q-signature=14e6ebd7955b0c6da532151bf97045e2c5a64e10
Hello world

結論:演算法如果能得到Authorization 後的那一串字串即為正確

準備工作

來看一下(官方提供的)使用者資訊以及HTTP資訊:

    SecretId:AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q
  • SecretKey:BQYIM75p8x0iWVFS
  • SecretKey簽章有效起始時間:1417773892
  • 簽章有效停止時間:1417853898
  • HTTP原始請求頭:根據上一節範例不難得到HTTP原始請求有三個內容Host、x-cos-content-sha1 和x-cos-storage-class
  • #HTTP請求參數:是PUT 請求,沒有?參數
  • #計算簽章
將準備工作中的各項參數帶入請求簽章規則,不難就可以得到結果,如下表:

鍵(key)值(value)備註q-sign-algorithmsha1目前僅支援sha1 簽章演算法q-akAKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q#SecretId 欄位q-sign-time1417773892;14178538982014/12/5 18:04:52 到2014/12/6 16:18: 18q-key-time1417773892;14178538982014/12/5 18:04:52 到2014/12/6 16 :18:18q-header-listhost;x-cos-content-sha1;x-cos-storage-class

##################### HTTP 頭部key 的字典順序排序清單############q-url-param-list###############HTTP 參數清單為空## ##########q-signature######14e6ebd7955b0c6da532151bf97045e2c5a64e10######透過程式碼計算所得#####################

但 q-signature 怎么来的?

刚才说到,q-signature 也需要特定算法计算得来,下面就说明如何计算

计算请求签名

先看代码:

/**
 * 计算签名
 * 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 = &#39;&#39;;

 //compute signature
 $httpMethod = &#39;put&#39;;
 $httpUri = $fileUri;

 //与 q-url-param-list 相同
 $httpParameters = $url_param_list;

 //将自定义请求头分解为 & 连接的字符串
 $headerString = get_http_header_string( $headers );

 // 计算签名中的 signature 部分
 $signTime = $qSignTime;
 $signKey = hash_hmac(&#39;sha1&#39;, $signTime, $secretKey);
 $httpString = "$httpMethod\n$httpUri\n$httpParameters\n$headerString\n";
 $sha1edHttpString = sha1($httpString);
 $stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
 $signature = hash_hmac(&#39;sha1&#39;, $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...

$header_list 这个值要符合 q-header-list 规则因此需要计算,逻辑是上文已经描述,是从既定的请求项中抽出 key 组成有序字符串,代码如下:

/**
 * 按COS要求对header_list内容进行转换
 * 提取所有key
 * 字典排序
 * key转换为小写
 * 多对key=value之间用连接符连接
 * 
 */
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(&#39;;&#39;, $tmpArray);
 }
 catch(Exception $error){
  return false;
 }
}

$url-param-list 上面讲过,这个值是HTTP请求参数,对于 PUT 方法没有 ? 参数,自然值为空,所以代码中“偷懒”直接给了空字符串。

Signature 的计算和需要小心的地方

官方已经给出了完整的算法,PHP 甚至还有写好的代码,应该是很幸福了(但!由于看官方文档看的头晕还是踩了坑,随后一起说明),先看一下 signature 的“格式”:

SignKey = HMAC-SHA1(SecretKey,"[q-key-time]")
HttpString = [HttpMethod]\n[HttpURI]\n[HttpParameters]\n[HttpHeaders]\n
StringToSign = [q-sign-algorithm]\n[q-sign-time]\nSHA1-HASH(HttpString)\n
Signature = HMAC-SHA1(SignKey,StringToSign)

再看一下 Signature 的完整算法:

$signTime = $qSignTime;
$signKey = hash_hmac(&#39;sha1&#39;, $signTime, $secretKey);
$httpString = "$httpMethod\n$httpUri\n$httpParameters\n$headerString\n";
$sha1edHttpString = sha1($httpString);
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
$signature = hash_hmac(&#39;sha1&#39;, $stringToSign, $signKey);

$signTime:很简单,起止时间组成的字符串,从上文拿来直接用
$signKey:HMAC-SHA1 算法直接计算即可
$httpString:四个部分组成需要分开说
1、$httpMethod:HTTP请求方法,小写,比如 put、get
2、$httpUri:HTTP请求的URI部分,从“/”虚拟根开始,如 /testfile 说明在存储桶根目录下创建一个叫 testfile 的文件,/image/face1.jpg 说明在根目录/image目录下建立一个叫 face1.jpg 的文件,至于是不是图片文件,不管
3、$httpParameters:这是第一个需要小心的地方。由HTTP原始请求参数组成,即请求 URI 中 ? 后面的部分,本例调用的是 PUT Object 接口,因此为空。如果不为空,需要把请求参数每一项的 key 和 value 均转换小写,多对 key=value 按字典排序并以 & 相连接
4、$headerString:这是第二个需要小心的地方,由 HTTP 原始请求头组成,根据请求头,选择全部或部分请求头,把每项的key都转换为小写,把value都进行URLEncode转换,每项格式都改为key=value,然后按照key进行字典排序,最后把它们用连接符 & 组成字符串。这是我整理的逻辑,代码如下:

/**
 * 按COS要求从数组中获取 Signature 中 [HttpString] 内容
 * 标准格式 key=value&key=value&... 
 * 数组元素按键字典排序 * 
 * key转换为小写
 * value进行UrlEncode转换
 * 转换为key=value格式
 * 多对key=value之间用连接符连接
 * 
 */
function get_http_header_string($headers){
 if(!is_array($headers)){
  return false;
 }

 try{
  $tmpArray = array();
  foreach($headers as $key => $value){
   $tmpKey = strtolower($key);
   $tmpArray[$tmpKey] = urlencode($value);
  }
  ksort($tmpArray);
  $headerArray = array();
  foreach( $tmpArray as $key => $value){
   array_push($headerArray, "$key=$value");
  }
  return implode(&#39;&&#39;, $headerArray);
 }
 catch(Exception $error){
  return false;
 }
}

为什么要小心?

HTTP原始请求头和请求参数用在了四个地方,分别是请求签名里的 q-header-list 和 Signature 里的 HttpHeaders——两者都用到了HTTP原始请求头;请求签名里的 q-url-param-list 和 Signature 里的 HttpParameters——两者都用到了HTTP请求参数。一定要保证HTTP请求头和请求参数所选用的数量和对象一致

  • 相同:生成 q-header-list 的HTTP请求头数量和成员要和生成 HttpHeaders 的相同,生成 q-url-param-list 的HTTP请求参数数量和成员要和生成 HttpParameters 的相同

  • 不同:q-header-list 和 q-url-param-list 只取 key 部分,HttpHeaders 和 HttpParameters 取 key 和 value 部分

输出结果和校验

至此,请求签名中7个值都有了,有的是来自用户信息,有的需要计算,需要计算的上面也给出了所有的计算方法和为什么如此计算的个人理解。最后只需要按照官方要求进行输出即可。看一下

以上是PHP產生騰訊雲COS介面所需的請求簽名的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn