概述
Authorization請求頭包含以下信息(增加換行是為了方便閱讀,實際為空字符串):
Authorization: AWS4-HMAC-SHA256
Credential=2a948fd3f00ba0925806/20180501/region/s3/aws4_request,
SignedHeaders=host;range;x-amz-date,
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
組成字段說明如下:
字段 描述 AWS4-HMAC-SHA256
用于簽名的算法,固定值。 Credential 用戶AccessKeyID和范圍信息,范圍信息包括請求日期、區域、服務、終止字符串aws4_request,格式如下:
AccessKeyID/date/region/service/aws4_request
其中:
date格式為YYYYMMDD。
region:
對于oos api:訪問域名為oos-xx.ctyunapi.cn,region為xx。對于統計api:訪問域名為oos-xx-mg.ctyunapi.cn,region為xx-mg。
對于操作跟蹤api:訪問域名為oos-xx-cloudtrail.ctyunapi.cn,region為xx。
對于iam api:訪問域名為oos-xx-iam.ctyunapi.cn,region為xx。
各資源池的詳細訪問域名詳見域名(Endpoint)列表。service:
若使用OOS API服務,service為s3。
若使用統計分析服務,service為s3。
若使用操作跟蹤服務,service為cloudtrail。
若使用IAM服務,service為sts。SignedHeaders 已簽名請求頭的列表。該列表只需包含請求頭名字,用分號分隔,必須全部小寫,并按字符順序對其進行排序,示例如下:
host;range;x-amz-date。
Signature 計算出的256位簽名信息,以64個小寫十六進制字符串形式表示。
有兩種簽名計算方式:
- 簽名負載方式 :用戶可以選擇計算整個負載(即請求體)的checksum,并將其包含在簽名計算中。這種方式提高了安全性,但用戶需要讀取兩次負載或將其緩沖在內存中。我們建議用戶包含負載checksum以增強安全性。
- 無簽名負載方式 :在簽名計算中不包括負載的checksum。將值設置為文本字符串UNSIGNED_PAYLOAD,直接作為簽名計算。
上述兩種方式,都必須攜帶x-amz-content-sha256請求頭,如果選擇簽名負載方式,請將x-amz-content-sha256請求頭的值設置為負載的checksum值,否則將值設置為文本字符串UNSIGNED-PAYLOAD。
簽名過程
簽名過程如下圖所示:

下表描述了圖中顯示的功能。用戶需要為這些函數實現代碼。
功能 描述 Lowercase() 將字符串轉換為小寫。 Hex() 小寫16進制編碼。 SHA256Hash() 安全散列算法(SHA)加密散列函數。 HMAC-SHA256() 使用簽名密鑰,根據SHA256算法計算出的簽名值。 Trim() 刪除任何前導或尾隨空格。 UriEncode() URI編碼每個字節。UriEncode()必須強制執行以下規則:
除下列字符外,其他字符進行URI編碼:'A' - 'Z','a' - 'z','0' - '9',' - ','.','_'和'~'。
空格字符是保留字符,必須編碼為“%20”(而不是“+”)。
每個URI編碼字節由'%'和兩位十六進制值組成。
十六進制值中的字母必須為大寫,例如“%1A”。
除了文件名之外,對正斜杠字符'/'進行編碼。例如,如果文件名稱為 photos/Jan/sample.jpg,則不對名稱中的正斜杠進行編碼。
說明建議用戶編寫自己的自定義UriEncode函數,以確保您的編碼可以正常工作。
以下是Java中的示例UriEncode()函數。
public static String UriEncode(CharSequence input, boolean encodeSlash) {
? ? ? ? ? StringBuilder result = new StringBuilder();
? ? ? ? ? for (int i = 0; i < input.length(); i++) {
? ? ? ? ? ? ? char ch = input.charAt(i);
? ? ? ? ? ? ? if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') {
? ? ? ? ? ? ? ? ? result.append(ch);
? ? ? ? ? ? ? } else if (ch == '/') {
? ? ? ? ? ? ? ? ? result.append(encodeSlash ? "%2F" : ch);
? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? result.append(toHexUTF8(ch));
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? ? return result.toString();
? ? ? }
-
創建規范請求
將請求的內容(包括主機、操作、請求頭等)組織為標準規范格式。規范請求是用于創建待簽字符串的輸入之一。偽代碼如下:
CanonicalRequest = HTTPRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalQueryString + '\n' + CanonicalHeaders + '\n' + SignedHeaders + '\n' + HexEncode(Hash(RequestPayload))-
HTTPMethod是HTTP方法,例如GET,PUT,HEAD和DELETE。
-
CanonicalURI是URI的絕對路徑,以域名后面的“/”開頭,直到字符串的末尾或者問號字符('?')截止。例如/examplebucket/myphoto.jpg。
-
CanonicalQueryString是URI編碼后的查詢字符串參數。用戶需要單獨對參數名稱和值進行URI編碼。并需要按參數名稱的字母順序,對參數進行排序。排序在編碼后進行。以下URI示例中的查詢字符串是 prefix=somePrefix&marker=someMarker&max-keys=20:
//oos-cn.ctyunapi.cn/examplebucket?prefix=somePrefix&marker=someMarker&max-keys=20CanonicalQueryString的構造方式如下(為了便于閱讀,添加了換行符):
UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")當請求的目標是子資源時,相應的查詢參數的值設置為空字符串(“”)。例如,下面的請求用于設置Bucket的ACL權限:
//oos-cn.ctyunapi.cn/examplebucket?acl在這種情況下,CanonicalQueryString為:
UriEncode("acl") + "=" + ""如果URI中不包含“?”,則請求中不存在查詢字符串,此時將CanonicalQueryString設置為空字符串(“”),但仍需要包含“\ n”。
-
CanonicalHeaders是請求頭的列表:
各個請求頭名稱和值由換行符(“\ n”)分隔。請求頭名稱必須為小寫。如果有相同名字的請求頭,則根據標準RFC 2616, 4.2章進行合并(兩個值之間只用英文逗號分隔)。如有兩個名為'x-amz-meta-name'的請求頭,對應的值分別為'fred'和'barney',則合并后為:'x-amz-meta-name:fred,barney'。刪除分隔符(:)兩端和值兩端出現的任何空格。如'x-amz-meta-name : fred '轉換成:'x-amz-meta-name:fred'。需要按字母順序對請求頭名稱進行排序。
示例如下:Lowercase(Trim(<HeaderName1>))+":"+Trim(<value>)+"\n" Lowercase(Trim(<HeaderName2>))+":"+Trim(<value>)+"\n" ... Lowercase(Trim(<HeaderNameN>))+":"+Trim(<value>)+"\n"CanonicalHeaders列表必須包括以下內容:HTTP Host標頭。如果存在Content-Type請求頭,則必須將其添加到CanonicalHeaders列表中。所有x-amz-*請求頭,例如,如果您使用的是臨時安全憑據,則需要在請求中包含x-amz-security-token,必須將此標題添加到CanonicalHeader列表中。
以下是CanonicalHeaders的示例,請求頭名稱為小寫并已排序。
host:oos-cn.ctyunapi.cn x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130708T220855Z -
SignedHeaders是按字母順序排序的,以分號分隔的小寫請求頭名稱列表。列表中的請求頭與用戶在CanonicalHeaders字符串中包含的請求頭相同。例如,對于前面的示例,SignedHeaders的值為:
host;x-amz-content-sha256;x-amz-date -
RequestPayload是請求負載的SHA256哈希的十六進制值。
如果請求中沒有負載,則計算空字符串的哈希值,如下所示:Hex(SHA256Hash(""))哈希返回以下值:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855例如:當用戶使用PUT請求上傳文件時,用戶可以在請求體中提供文件數據。使用GET請求檢索文件時,沒有請求體,所以計算空字符串的哈希。
-
-
創建待簽名字符串
待簽名的字符串格式如下:
"AWS4-HMAC-SHA256" + "\n" + timeStampISO8601Format + "\n" +<Scope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))常量字符串AWS4-HMAC-SHA256指定用戶使用的哈希算法HMAC-SHA256。
timeStamp是ISO 8601格式的當前UTC時間(例如20180501T000000Z)。
Scope是將生成的簽名綁定到指定日期,OOS區域和服務。
date.Format(<YYYYMMDD>) + "/" + <region> + "/" + <service> + "/aws4_request" -
計算簽名
使用SecretAccessKey作為初始哈希操作的密鑰,對請求日期、區域和服務執行一系列加密哈希操作(HMAC 操作),從而派生簽名密鑰。偽代碼如下:DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "< region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")最終簽名是使用簽名密鑰作為密鑰,對待簽名字符串計算得到HMAC-SHA256哈希值。偽代碼如下:
HMAC-SHA256(SigningKey, StringToSign) -
將簽名信息添加到請求頭
在計算簽名后,將其添加到請求的HTTP請求頭或查詢字符串中。
將簽名信息添加到Authorization標頭的偽代碼如下:
Authorization: <algorithm> Credential=<ak>/<credential_scope>, SignedHeaders=<SignedHeaders>, Signature=<signature>
示例
以下是使用V4簽名的示例。示例中使用的訪問密鑰如下:
| 參數 | 值 |
|---|---|
| AccessKeyID | 2a948fd3f00ba0925806 |
| SecretAccessKey | ef2017c2e5ffa0b1761717ecbca021da16501384 |
Bucket名稱:example-bucket。
訪問的域名是oos-cn.ctyunapi.cn, region是cn。
示例:GET文件
從存儲桶example-bucket中獲取文件test.txt的前10個字節。請求如下:
GET /test.txt HTTP/1.1
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Authorization: SignatureToBeCalculated
x-amz-date: 20190220T060724Z
Range: bytes=0-9
Host: example-bucket.oos-cn.ctyunapi.cn
由于此GET請求不提供任何請求體內容,因此該x-amz-content-sha256請求頭的值是空請求體的哈希值。以下步驟顯示Authorization請求頭的計算的方法。
- StringToSign
-
創建規范請求
GET /test.txt host:example-bucket.oos-cn.ctyunapi.cn range:bytes=0-9 x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20190220T060724Z host;range;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855其中,最后一行是空請求體的hash值。第三行是空,因為此請求不包含請求參數。
-
待簽名字符串
AWS4-HMAC-SHA256 20190220T060724Z 20190220/cn/s3/aws4_request a6417debbe1fe886b8ed84dca872475f7f09b01961af10d30fa601bc0986ba36
-
- 生成簽名密鑰
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<SecretAccessKey>","20190220"),"cn"),"s3"),"aws4_request") - 計算后的簽名
dcefeb864c1ffad98f8f0307af32ceb584b38dc2a9c7a65459363cdb03fc6f12 - Authorization請求頭
Authorization: AWS4-HMAC-SHA256 Credential=2a948fd3f00ba0925806/20190220/cn/s3/aws4_request, SignedHeaders=host;range;x-amz-content-sha256;x-amz-date, Signature=dcefeb864c1ffad98f8f0307af32ceb584b38dc2a9c7a65459363cdb03fc6f12
示例:PUT文件
在存儲桶example-bucket中上傳文件test.txt。
PUT /test.txt HTTP/1.1
x-amz-content-sha256: 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9
Authorization:SignatureToBeCalculated
x-amz-date: 20190220T070722Z
x-amz-storage-class: STANDARD
Host: example-bucket.oos-cn.ctyunapi.cn
Content-Length: 12
hello world!
以下步驟顯示Authorization請求頭的計算的方法。
- StringToSign
-
創建規范請求
PUT /test.txt content-length:12 host:example-bucket.oos-cn.ctyunapi.cn x-amz-content-sha256:7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9 x-amz-date:20190220T070722Z x-amz-storage-class:STANDARD content-length;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9其中,第三行是空,因為此請求不包含請求參數。最后一行是請求體的hash值,它必須與x-amz-content-sha256 請求頭的值相同。
-
待簽名字符串
AWS4-HMAC-SHA256 20190220T070722Z 20190220/cn/s3/aws4_request 013accc1b2460f530908e106224c57d9fcf9ed74986f5399e27196b73824ddf3
-
- 生成簽名密鑰
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<SecretAccessKey>","20190220"),"cn"),"s3"),"aws4_request") - 計算后的簽名
5c4e3bc9b2589f2d451a7570cb1283637691f95671525fb0223a1fd158f5fee1 - Authorization請求頭
Authorization: AWS4-HMAC-SHA256 Credential=2a948fd3f00ba0925806/20190220/cn/s3/aws4_request, SignedHeaders=contentlength;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class, Signature=5c4e3bc9b2589f2d451a7570cb1283637691f95671525fb0223a1fd158f5fee1
示例:列出存儲桶中的文件
列出存儲桶example-bucket中的文件,prefix設置為“t”,最多返回2個文件。請求如下:
GET /?max-keys=2&prefix=t HTTP/1.1
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Authorization: SignatureToBeCalculated
x-amz-date: 20190220T085955Z
Host: example-bucket.oos-cn.ctyunapi.cn
以下步驟顯示Authorization請求頭的計算的方法。
- StringToSign
-
創建規范請求
GET / max-keys=2&prefix=t host:example-bucket.oos-cn.ctyunapi.cn x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20190220T085955Z host;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855其中,最后一行是空請求體的hash值。
-
待簽名字符串
AWS4-HMAC-SHA256 20190220T085955Z 20190220/cn/s3/aws4_request 3b6553685b6c201cd38cb1077fe657b0f55b355e7ae011e31fa244d009c4d43a
-
- 生成簽名密鑰
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<SecretAccessKey>","20190220"),"cn"),"s3"),"aws4_request") - 計算后的簽名
72c3758e3b8f27a1a9d9d38b4c143329d3094bc8156d28581bfdd5b7663d6ca8 - Authorization請求頭
Authorization: AWS4-HMAC-SHA256 Credential=2a948fd3f00ba0925806/20190220/cn/s3/aws4_request, SignedHeaders=host;x-amzcontent-sha256;x-amz-date, Signature=72c3758e3b8f27a1a9d9d38b4c143329d3094bc8156d28581bfdd5b7663d6ca8