请求签名

最近更新时间:2019-04-17 16:48:11

注意:

  1. 此文档仅适用于 COS XML 版本,可登录后在 COS 控制台首页查看。
  2. 此文档不适用于 POST object 的 HTTP 请求。

使用对象存储服务 COS 时,可通过 RESTful API 对 COS 发起 HTTP 匿名请求或 HTTP 签名请求,对于签名请求,COS 服务器端将会进行对请求发起者的身份验证。

  • 匿名请求:HTTP 请求不携带任何身份标识和鉴权信息,通过 RESTful API 进行 HTTP 请求操作。
  • 签名请求:HTTP 请求时添加签名,COS 服务器端收到消息后,进行身份验证,验证成功则可接受并执行请求,否则将会返回错误信息并丢弃此请求。

腾讯云对象存储 COS 基于密钥 HMAC(Hash Message Authentication Code) 的自定义 HTTP 方案进行身份验证。
腾讯云对象存储目前提供了 COS 签名工具 供用户生成签名,如有需要可前往使用。

签名使用场景

在 COS 对象存储服务使用的场景中,对于需要对外发布类的数据,通常可将对象设置为公有读,私有写。即所有人可查看,通过 ACL 策略指定账号或 IP 可写入。此时,可将 ACL 策略与 API 请求签名相结合,对访问进行身份验证,并对操作进行权限和有效期的控制。

注意:

本文所描述的 API 请求签名,如果您使用 SDK 进行开发,则已包含在内。仅在您希望通过原始 API 进行二次开发时,需要根据本文所描述步骤进行操作

在以上场景中,可对 API 请求进行多方面的安全防护:

  1. 请求者身份验证。通过访问者唯一 ID 和密钥确定请求者身份。
  2. 防止传输数据篡改。对数据加密并检验,保障传输内容完整性。
  3. 防止签名被盗用。对签名设置时效,且进行数据加密,避免签名盗用并重复使用。

签名流程

客户通过对 HTTP 请求进行签名,并将签名后的请求发送至腾讯云进行签名验证,具体流程如下图所示。
流程图

准备工作

  1. APPID、SecretId 和 SecretKey。
    在访问管理控制台的 API 密钥管理 页面中获取。
  2. 确定开发语言:
    支持但不限于 Java、PHP 、C Sharp、C++、 Node.js、Python,根据不同的开发语言,确定对应的 HMAC-SHA1、SHA1 函数。

签名内容

通过 RESTful API 对 COS 发起的 HTTP 签名请求,使用标准的 HTTP Authorization 头部来传递,如下例所示:

PUT ?versioning HTTP/1.1
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
Authorization: q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&q-sign-time=1480932292;1481012298&q-key-time=1480932292;1481012298&q-header-list=host&q-url-param-list=versioning&q-signature=438023e4a4207299d87bb75d1c739c06cc9406bb

其中,签名内容由多个 key=value 对,通过 “&” 连接而成,格式如下:

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) 值(value) 描述 是否必填
q-sign-algorithm sha1 签名算法,目前仅支持 sha1,即为 sha1
q-ak 参数[SecretID] 帐户 ID,即 SecretId,在访问管理控制台的 API 密钥管理 页面可获取
例如:AKIDQjz3ltompVjBni5LitkWHFxxxxxxxxxx
q-sign-time 参数[SignTime] 本签名的有效起止时间,通过 Unix 时间戳 描述起始和结束时间,以秒为单位,格式为 [start-seconds];[end-seconds]
例如: 1480932292;1481012298
q-key-time 参数[KeyTime] 与 q-sign-time 值相同
q-header-list 参数[SignedHeaderList] HTTP 请求头部。需从key:value中提取部分或全部 key,且 key 需转化为小写,并将多个 key 之间以字典顺序排序,如有多组 key,可用;连接。
例如:
HTTP 请求示例中:
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
Content-Type: image/jpeg
Content-Length: 10240
其 SignedHeaderList 为 content-Length;content-type;host
q-url-param-list 参数[SignedParameterList] HTTP 请求参数。需从 key=value 中提取部分或全部 key,且 key 需转化为小写,并将多个 key 之间以字典顺序排序,如有多组 key,可用;连接。
例如: HTTP 请求GET /?prefix=abc&max-keys=20,其则 SignedParameterList 为 max-keys;prefix 或者 prefix
q-signature 参数[Signature] HTTP 内容签名,请查看 Signature 计算

说明:

关于 q-sign-time 和 q-key-time 的说明:

  1. Unix 时间戳是从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
  2. 结束时间戳需要大于起始时间戳,否则将会导致签名马上过期。
  3. 计算签名和发送请求时,请确保本机时间已经与国际标准时间校准,如误差过大,服务端将拒绝相关请求。

Signature 计算

Signature 的计算分为四个步骤:

  1. 对签名的有效起止时间加密计算值 SignKey。
  2. 根据固定格式组合生成 HttpString。
  3. 加密 HttpString,并根据固定格式组合生成 StringToSign。
  4. 加密 StringToSign,生成 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)

其中,在不同的开发语言环境,请用不同的语言规范更新代码,包含:

  1. 变量的定义与赋值,请根据所使用开发语言的规范更新。
  2. 伪函数 SHA1-HASH,输出为16进制小写。

加密算法示例

不同语言如何调用 HMAC-SHA1 和 SHA1-HASH 可以参考下面的示例:

PHP

$sha1HttpString = sha1('ExampleHttpString');

$signKey = hash_hmac('sha1', 'ExampleKeyTime', 'YourSecretKey');

Java

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.HmacUtils;

String sha1HttpString = DigestUtils.sha1Hex("ExampleHttpString");

String signKey = HmacUtils.hmacSha1Hex("YourSecretKey", "ExampleKeyTime");

Python

import hmac
import hashlib

sha1 = hashlib.sha1()
sha1_http_string = sha1.update('ExampleHttpString'.encode('utf-8')).hexdigest()

sign_key = hmac.new('YourSecretKey'.encode('utf-8'), 'ExampleKeyTime'.encode('utf-8'), hashlib.sha1).hexdigest()

Node.js

var crypto = require('crypto');

var sha1HttpString = crypto.createHash('sha1').update('ExampleHttpString').digest('hex');
var signKey = crypto.createHmac('sha1', 'YourSecretKey').update('ExampleKeyTime').digest('hex');

Go

import (
    "crypto/hmac"
    "crypto/sha1"
)

h := sha1.New()
h.Write([]byte("ExampleHttpString"))
sha1HttpString := h.Sum(nil)

var hashFunc = sha1.New
h = hmac.New(hashFunc, []byte("YourSecretKey"))
h.Write([]byte("ExampleKeyTime"))
signKey := h.Sum(nil)

参数说明

参数 说明
[q-key-time] 必须与 键值描述 中所填写的 q-key-time 保持一致
[HttpMethod] HTTP 请求方法。仅支持小写,即可为 get,post,put,delete,head,options。
例如: HTTP 请求GET /testfile,其 HttpMethod 为 get
[HttpURI] HTTP 请求 URI 部分。即从/虚拟根路径开始部分
例如: HTTP 请求GET /testfile,其 HttpURI 为/testfile
注意:如 URI 中包含中文或者特殊字符,均不需要进行 URLEncode
[HttpParameters] HTTP 请求参数。即为 URI 中?之后由&连接的部分,需选取全部或部分 key=value,且 key 需转换为小写,value 需进行 URLEncode 转换,多对 key=value 对之间以 “&” 相连接,并以字典顺序排序
例如: HTTP 请求GET /?prefix=abc&max-keys=20,其 HttpParameters 为 max-keys=20&prefix=abc 或 prefix=abc
注意:所包含的 key=value 对中的 key 必须与 键值描述 中所填写的 q-url-param-list 中的 key 保持一致
[HttpHeaders] HTTP 请求头部。需选取全部或部分 key:value,并将其转化为 key=value 格式,且 key 需转换为小写,value 需进行 URLEncode 转换,多对 key=value 对之间以&相连接,并以字典顺序排序
例如: HTTP 请求Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com Content-Type: image/jpeg,其 HttpHeaders 为 content-type=image%2Fjpeg&host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com
注意:所包含的 key=value 对中的 key 必须与 键值描述 中所填写的 q-header-list 中的 key 保持一致
[q-sign-algorithm] sha1,目前仅支持 sha1 加密算法
[q-sign-time] 必须与 键值描述 中所填写的 q-sign-time 保持一致

参数实例

参数
[q-key-time] 1417773892;1417853898
[HttpMethod] get
[HttpURI] /testfile
[HttpParameters] max-keys=20&prefix=abc
[HttpHeaders] host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com
[q-sign-algorithm] sha1
[q-sign-time] 1417773892;1417853898

举例说明

如某用户希望使用 API 调用方式下载和上传对象,并对调用进行签名。

准备工作

登录访问管理控制台的 API 密钥管理 页面获取其 APPID、SecretId 和 SecretKey,并确定开发语言,分别如下:

APPID SecretId SecretKey 开发语言
1250000000 AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q BQYIM75p8x0iWVFSIgqEKwFprpRSVHlz PHP

上传对象

需求:上传对象到存储桶 examplebucket

原始 HTTP 请求为:

PUT /exampleobject HTTP/1.1
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
x-cos-storage-class: standard

Hello world

签名后的 HTTP 请求为:

PUT /exampleobject HTTP/1.1
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
x-cos-storage-class: standard
x-cos-content-sha1: 7b502c3a1f48c8609ae212cdfb639dee39673f5e
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

各参数对应的值和描述如下:

键(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 ad4e18acbb15034825abcc49806cf6d761be4829 通过代码计算所得

其中,q-signature 的计算代码为:

$signTime = '1417773892;1417853898';
$keyTime = $signTime;
$signKey = hash_hmac('sha1', $keyTime, 'BQYIM75p8x0iWVFSIgqEKwFprpRSVHlz');
$httpString = "put\n/exampleobject\n\nhost=examplebucket-1250000000.cos.ap-beijing.myqcloud.com&x-cos-content-sha1=7b502c3a1f48c8609ae212cdfb639dee39673f5e&x-cos-storage-class=standard\n";
$sha1edHttpString = sha1($httpString);
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
$signature = hash_hmac('sha1', $stringToSign, $signKey);

下载对象

需求:下载存储桶 examplebucket 中的对象前4个字节。

原始 HTTP 请求为:

GET /exampleobject HTTP/1.1
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
Range: bytes=0-3

签名后的 HTTP 请求为:

GET /exampleobject HTTP/1.1
Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
Range: bytes=0-3
Authorization: q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&q-sign-time=1417773892;1417853898&q-key-time=1417773892;1417853898&q-header-list=host;range&q-url-param-list=&q-signature=4b6cbab14ce01381c29032423481ebffd514e8be

各参数对应的值和描述如下:

键(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;range HTTP 头部 key 的列表
q-url-param-list - HTTP 参数列表为空
q-signature 4b6cbab14ce01381c29032423481ebffd514e8be 通过代码计算所得

其中,q-signature 的计算代码为:

$signTime = '1417773892;1417853898';
$keyTime = $signTime;
$signKey = hash_hmac('sha1', $keyTime, 'BQYIM75p8x0iWVFSIgqEKwFprpRSVHlz');
$httpString = "get\n/testfile\n\nhost=examplebucket-1250000000.cos.ap-beijing.myqcloud.com&range=bytes%3D0-3\n";
$sha1edHttpString = sha1($httpString);
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
$signature = hash_hmac('sha1', $stringToSign, $signKey);