簽署和驗證請求 REST - Amazon Simple Storage Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

簽署和驗證請求 REST

注意

本主題說明如何使用 Signature 第 2 版驗證要求。Amazon S3 現在支援最新的 Signature 第 4 版。所有區域都支援此最新的 Signature 版本,而且 2014 年 1 月 30 日以後的任何新區域只會支援 Signature 第 4 版。如需詳細資訊,請參閱 Amazon 簡單儲存服務API參考中的驗證請求(AWS 簽名版本 4)

身分驗證是向系統表明身分的程序。身分是 Amazon S3 存取控制決策中很重要的因素。要求的允許或拒絕部分取決於要求者的身分。例如,建立儲存貯體的權利會保留給已註冊的開發人員,而 (根據預設) 建立儲存貯體中物件的權利則保留給討論中之儲存貯體的擁有者。身為開發人員,您會提出要求來叫用這些權限,因此您需要透過驗證要求,向系統表明身分。本節將告訴您如何做到。

注意

本節中的內容不適用於HTTPPOST。如需詳細資訊,請參閱以瀏覽器為基礎的上傳使用 POST (AWS 簽名版本 2)

Amazon S3 REST API 使用以鍵入 HMAC (雜湊訊息身份驗證碼) 為基礎的自訂HTTP配置進行身份驗證。若要驗證要求,請先將要求的選取元素串連成一個字串。然後,您可以使用 AWS 密鑰訪問密鑰來計算該字符串HMAC的。非正式地,我們將此過程稱為「簽署請求」,然後我們將HMAC算法的輸出稱為簽名,因為它模擬了真實簽名的安全性屬性。最後,請使用本節中所述的語法,將此簽章新增為要求的參數。

當系統收到經過驗證的請求時,它會獲取您聲稱擁有的 AWS 秘密訪問密鑰,並以相同的方式使用它來計算收到的消息的簽名。然後,它會將所計算的簽章與要求者提供的簽章進行比較。如果兩個簽章相符,則系統會得出結論,要求者必須擁有 AWS 秘密存取金鑰的存取權,因此會與發行金鑰之主體的授權進行作業。如果兩個簽章不符,則會捨棄要求,且系統會回應錯誤訊息。

範例 經過驗證的 Amazon S3 REST
GET /photos/puppy.jpg HTTP/1.1 Host: awsexamplebucket1.us-west-1.s3.amazonaws.com Date: Tue, 27 Mar 2007 19:36:42 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE: qgk2+6Sv9/oM7G3qLEjTH1a1l1g=

使用臨時安全登入資料

如果您使用暫時性安全登入資料簽署要求 (請參閱「提出要求」),您必須新增 x-amz-security-token 標頭,以在您的要求中包含對應的安全字符。

當您使用取得臨時安全登入資料時 AWS Security Token Service API,回應會包含暫時的安全性登入資料和工作階段 Token。當您將請求傳送至 Amazon S3 時,您會在 x-amz-security-token 標頭中提供此工作階段字符值。如需 AWS Security Token Service API提供的相關資訊IAM,請移至《AWS Security Token Service API參考指南》中的「動作」。

Authentication 標頭

Amazon S3 REST API 使用標準標HTTPAuthorization頭來傳遞身份驗證資訊。(標準標頭的名稱並不適當,因為它傳遞身分驗證資訊,而不是身分驗證)。根據 Amazon S3 身分驗證機制,Authorization 標頭的格式如下:

Authorization: AWS AWSAccessKeyId:Signature

開發人員在註冊時會 AWS 獲得存取金鑰 ID 和 AWS 秘密存取金鑰。進行要求身分驗證時,AWSAccessKeyId 元素會識別用來計算簽章的存取金鑰 ID;間接來說,就是提出要求的開發人員。

Signature元素是 RFC 2104 HMAC-從請求中選擇SHA1的元素,因此授權頭的一Signature部分將因請求而異。如果系統計算的請求簽名與請求中Signature包含的簽名匹配,則請求者將證明擁有該 AWS 秘密訪問密鑰。此要求接著會以金鑰核發對象的開發人員身分 (具授權) 進行處理。

下列虛擬語法說明 Authorization 要求標頭的建構 (在此範例中,\n 表示 Unicode 字碼指標 U+000A,通常稱為新行字元)。

Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature; Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of(YourSecretAccessKey), UTF-8-Encoding-Of( StringToSign ) ) ); StringToSign = HTTP-Verb + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedAmzHeaders + CanonicalizedResource; CanonicalizedResource = [ "/" + Bucket ] + <HTTP-Request-URI, from the protocol name up to the query string> + [ subresource, if present. For example "?acl", "?location", or "?logging"]; CanonicalizedAmzHeaders = <described below>

HMAC-SHA1 是由 RFC2104-針對訊息驗證的金鑰雜湊所定義的演算法。該演算法接受兩個位元組字串、一個金鑰與一則訊息的輸入。對於 Amazon S3 請求身份驗證,請使用您的 AWS 秘密存取金鑰 (YourSecretAccessKey) 作為金鑰,使用 UTF -8 編碼StringToSign作為訊息。的HMAC輸出也SHA1是一個字節字符串,稱為摘要。Signature 要求參數是由編碼此 Digest 的 Base64 所建構。

將要求標準化以供簽署

之前提到,當系統收到經過驗證的要求時,它會將計算的要求簽章與要求中 StringToSign 所提供的簽章進行比較。因此,您必須使用 Amazon S3 所用的相同方法來計算簽章。我們將此以一致格式提出簽署請求的程序稱為標準化

構建元素 CanonicalizedResource

CanonicalizedResource 代表所要請求的 Amazon S3 資源。為REST請求構造它,如下所示:

1

從空字串 ("") 開始。

2

如果請求使用 Ho HTTP st 標頭(虛擬託管樣式)指定存儲桶,請在前面加上一個值區名稱"/"(例如,「/bucketname」)。針對路徑型要求及未定址儲存貯體的要求,則不用執行任何操作。如需虛擬託管型要求的詳細資訊,請參閱「儲存貯體的虛擬託管」。

對於虛擬託管樣式的請求 "https://awsexamplebucket1.s3.us-west-1.amazonaws.com/photos/puppy.jpg",CanonicalizedResource就是「/1」。

對於路徑樣式的請求,「https://s3.us-west-1.amazonaws.com/awsexamplebucket1/photos/puppy.jpg」,CanonicalizedResource是「」。

3

追加未解碼 R HTTP equest-的路徑部分URI,直到但不包括查詢字符串。

對於虛擬託管樣式的請求 "https://awsexamplebucket1.s3.us-west-1.amazonaws.com/photos/puppy.jpg",CanonicalizedResource則為 "/awsexamplebucket1/photos/puppy.jpg"。

對於路徑樣式的請求,「https://s3.us-west-1.amazonaws.com/awsexamplebucket1/photos/puppy.jpg」,CanonicalizedResource則為「/awsexamplebucket1/photos/puppy.jpg」。此時,虛擬託管型要求與路徑型要求的 CanonicalizedResource 會相同。

對於未解決存儲桶(例如GET服務)的請求,請附加「/」。

4

如果請求定址一項子資源 (例如 ?versioning?location?acl?lifecycle?versionid),請附加該子資源、其值 (若有) 與問號。請注意,在多個子資源的情況下,子資源必須按字典順序排序子資源名稱,並以「&」分隔,例如? acl& = versionIdvalue.

構建 CanonicalizedResource 元素時必須包含的子資源包括 acl,生命週期,位置,日誌記錄,通知partNumber,策略,requestPaymentuploadId,上傳,版本versionId,版本和網站。

如果請求指定查詢字串參數來覆寫回應標頭值 (請參閱 Get 物件),請附加查詢字串參數及其值。簽署時,您不會編碼這些值;不過,您必須在提出要求時編碼這些參數值。GET請求中的查詢字串參數包括response-content-typeresponse-content-languageresponse-expiresresponse-cache-controlresponse-content-disposition、和response-content-encoding

當您 CanonicalizedResource 為多物件刪除請求建立時,必須包含delete查詢字串參數。

來自 R HTTP equest-的 CanonicalizedResource 元素URI應該按照字面上的方式進行簽名,因為它們出現在HTTP請求中,包括 URL-Encode 中繼字符。

CanonicalizedResource能與HTTP請求不同URI。特別是,如果您的請求使用HTTPHost標頭來指定值區,則該值區不會出現在 R HTTP equest-中URI。不過,CanonicalizedResource 會繼續包含該儲存貯體。查詢字串參數可能也會出現在要求中,URI但不包含在中CanonicalizedResource。如需詳細資訊,請參閱儲存貯體的虛擬託管

構建元素 CanonicalizedAmzHeaders

若要建構的 CanonicalizedAmzHeaders 部分StringToSign,請選取所有以 'x-amz-' 開頭的HTTP要求標頭 (使用不區分大小寫的比較),然後使用下列程序。

1 將每個HTTP標題名稱轉換為小寫。例如,'X-Amz-Date' 會變成 'x-amz-date'。
2 按詞典編纂方式依標頭名稱排序標頭集合。
3 將具有相同名稱的頭字段合併為一個「標題名稱:comma-separated-value-list」對由 RFC 2616,第 4.2 節規定,值之間沒有任何空格。例如,兩個中繼資料標頭 'x-amz-meta-username: fred' 與 'x-amz-meta-username: barney' 會合併成單一標頭 'x-amz-meta-username: fred,barney'。
4 通過用單個空格替換折疊空格(包括換行符)來「展開」跨越多行的長標題(如 RFC 2616,第 4.2 節所允許)。
5 修剪標頭中冒號前後的任何空格。例如,標頭 'x-amz-meta-username: fred,barney' 會變成 'x-amz-meta-username:fred,barney'
6 最後,將新行字元 (U+000A) 附加至所產生之清單中的每個標準化標頭。通過將此列表中的所有頭文 CanonicalizedResource 件連接成一個字符串來構造元素。

位置與命名HTTP頭元素 StringToSign

StringToSign(內容類型,日期和內容-MD5)的前幾個頭元素在本質上是位置的。 StringToSign不包括這些標頭的名稱,只包括來自請求的值。相對的,'x-amz-' 元素是具名的。其標頭名稱與標頭值都會出現在 StringToSign 中。

如果在定義中呼叫的位置標頭不存在於您的StringToSign要求中 (例如,Content-Type或者對於要求而言Content-MD5是選用的,對於要PUT求而言沒有意義),GET請將空字串 (「」) 替換為該位置。

時間戳記需求

對於經過驗證的請求,必須使用有效的時間戳記(使用HTTPDate標頭或x-amz-date替代方法)。此外,經過驗證的請求所包含的用戶端時間戳記,必須在收到要求後不超過 Amazon S3 系統時間的 15 分鐘。否則,要求會失敗並出現 RequestTimeTooSkewed 錯誤碼。這些限制的用意是為了降低要求可能遭對手攔截而被重播的可能性。若要進一步防止竊聽,請針對已驗證的要求使用HTTPS傳輸。

注意

要求日期的驗證限制僅適用於未使用查詢字串身分驗證之經過驗證的要求。如需詳細資訊,請參閱「查詢字串要求身分驗證替代項」。

某些HTTP用戶端程式庫不會公開設定要求Date標頭的功能。如果您無法在標準化標頭中包含 'Date' 標頭的值,您可以改用 'x-amz-date' 標頭來設定要求的時間戳記。x-amz-date標頭的值必須是 RFC 2616 格式之一 (http://www.ietf.org/rfc/rfc2616.txt)。如果要求中有 x-amz-date 標頭,系統會在計算要求簽章時略過任何 Date 標頭。因此,如果您包含 x-amz-date 標頭,請在建構 Date 時,使用空字串來表示 StringToSign。如需範例,請參閱下一節。

身分驗證範例

本節中的範例使用下表中的 (非工作) 登入資料。

參數 Value
AWSAccessKeyId AKIAIOSFODNN7EXAMPLE
AWSSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

在範例 StringToSign 中,格式並不重要;而 \n 表示 Unicode 字碼指標 U+000A,通常稱為新行字元。此外,範例使用 "+0000" 來指定時區。您可以改用 "GMT" 來指定時區,但範例中顯示的簽名會有所不同。

物件 GET

此範例會從 awsexamplebucket1 儲存貯體取得物件。

請求 StringToSign
GET /photos/puppy.jpg HTTP/1.1 Host: awsexamplebucket1.us-west-1.s3.amazonaws.com Date: Tue, 27 Mar 2007 19:36:42 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE: qgk2+6Sv9/oM7G3qLEjTH1a1l1g=
GET\n \n \n Tue, 27 Mar 2007 19:36:42 +0000\n /awsexamplebucket1/photos/puppy.jpg

請注意, CanonicalizedResource 包括存儲桶名稱,但HTTP請求-URI 不包括。(儲存貯體是由 Host 標頭指定)。

注意

下列 Python 指令碼會使用提供的參數計算上述簽章。您可以使用此腳本來構建自己的簽名,並 StringToSign 在適當情況下替換密鑰。

import base64 import hmac from hashlib import sha1 access_key = 'AKIAIOSFODNN7EXAMPLE'.encode("UTF-8") secret_key = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'.encode("UTF-8") string_to_sign = 'GET\n\n\nTue, 27 Mar 2007 19:36:42 +0000\n/awsexamplebucket1/photos/puppy.jpg'.encode("UTF-8") signature = base64.b64encode( hmac.new( secret_key, string_to_sign, sha1 ).digest() ).strip() print(f"AWS {access_key.decode()}:{signature.decode()}")

物件 PUT

這個例子將物件放入 awsexamplebucket1 儲存貯體中。

請求 StringToSign
PUT /photos/puppy.jpg HTTP/1.1 Content-Type: image/jpeg Content-Length: 94328 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com Date: Tue, 27 Mar 2007 21:15:45 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE: iqRzw+ileNPu1fhspnRs8nOjjIA=
PUT\n \n image/jpeg\n Tue, 27 Mar 2007 21:15:45 +0000\n /awsexamplebucket1/photos/puppy.jpg

請注意要求和中的內容類型標頭。 StringToSign另請注意,內容-MD5 在中保留空白 StringToSign,因為它不存在於請求中。

清單

此範例列出 awsexamplebucket1 儲存貯體的內容。

請求 StringToSign
GET /?prefix=photos&max-keys=50&marker=puppy HTTP/1.1 User-Agent: Mozilla/5.0 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com Date: Tue, 27 Mar 2007 19:42:41 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE: m0WP8eCtspQl5Ahe6L1SozdX9YA=
GET\n \n \n Tue, 27 Mar 2007 19:42:41 +0000\n /awsexamplebucket1/

請注意查詢字串參數 CanonicalizedResource 和不存在的結尾斜線。

擷取

此範例會擷取 'awsexamplebucket1' 儲存貯體的存取控制政策子資源。

請求 StringToSign
GET /?acl HTTP/1.1 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com Date: Tue, 27 Mar 2007 19:44:46 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE: 82ZHiFIjc+WbcwFKGUVEQspPn+0=
GET\n \n \n Tue, 27 Mar 2007 19:44:46 +0000\n /awsexamplebucket1/?acl

請注意子資源查詢字串參數如何包含在中 CanonicalizedResource。

Delete

此範例會使用路徑型與 Date 替代項,從 'awsexamplebucket1' 儲存貯體中刪除物件。

請求 StringToSign
DELETE /awsexamplebucket1/photos/puppy.jpg HTTP/1.1 User-Agent: dotnet Host: s3.us-west-1.amazonaws.com Date: Tue, 27 Mar 2007 21:20:27 +0000 x-amz-date: Tue, 27 Mar 2007 21:20:26 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE:XbyTlbQdu9Xw5o8P4iMwPktxQd8=
DELETE\n \n \n Tue, 27 Mar 2007 21:20:26 +0000\n /awsexamplebucket1/photos/puppy.jpg

請注意我們如何使用指定日期的替代 x-amz-date '' 方法(因為我們的客戶端庫阻止我們設置日期,比如說)。在此情況下,x-amz-date 會優先於 Date 標頭。因此,簽章中的日期項目必須包含 x-amz-date 標頭的值。

上傳

此範例會將物件上傳至具有中繼資料的CNAME樣式虛擬託管值區。

請求 StringToSign
PUT /db-backup.dat.gz HTTP/1.1 User-Agent: curl/7.15.5 Host: static.example.com:8080 Date: Tue, 27 Mar 2007 21:06:08 +0000 x-amz-acl: public-read content-type: application/x-download Content-MD5: 4gJE4saaMU4BqNR0kLY+lw== X-Amz-Meta-ReviewedBy: joe@example.com X-Amz-Meta-ReviewedBy: jane@example.com X-Amz-Meta-FileChecksum: 0x02661779 X-Amz-Meta-ChecksumAlgorithm: crc32 Content-Disposition: attachment; filename=database.dat Content-Encoding: gzip Content-Length: 5913339 Authorization: AWS AKIAIOSFODNN7EXAMPLE: jtBQa0Aq+DkULFI8qrpwIjGEx0E=
PUT\n 4gJE4saaMU4BqNR0kLY+lw==\n application/x-download\n Tue, 27 Mar 2007 21:06:08 +0000\n x-amz-acl:public-read\n x-amz-meta-checksumalgorithm:crc32\n x-amz-meta-filechecksum:0x02661779\n x-amz-meta-reviewedby: joe@example.com,jane@example.com\n /static.example.com/db-backup.dat.gz

請注意 'x-amz-' 標頭如何排序、修剪多餘空格及轉換成小寫。另請注意,已聯結多個具有相同名稱的標頭,並使用逗號分隔其值。

請注意,只有Content-TypeContent-MD5HTTP實體標題如何顯示在StringToSign. 其他 Content-* 實體標頭則否。

同樣,請注意,CanonicalizedResource包括存儲桶名稱,但HTTP請求-URI 不包括。(儲存貯體是由 Host 標頭指定)。

列出我的所有儲存貯體

請求 StringToSign
GET / HTTP/1.1 Host: s3.us-west-1.amazonaws.com Date: Wed, 28 Mar 2007 01:29:59 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE:qGdzdERIC03wnaRNKh6OqZehG9s=
GET\n \n \n Wed, 28 Mar 2007 01:29:59 +0000\n /

Unicode 金鑰

請求 StringToSign
GET /dictionary/fran%C3%A7ais/pr%c3%a9f%c3%a8re HTTP/1.1 Host: s3.us-west-1.amazonaws.com Date: Wed, 28 Mar 2007 01:49:49 +0000 Authorization: AWS AKIAIOSFODNN7EXAMPLE:DNEZGsoieTZ92F3bUfSPQcbGmlM=
GET\n \n \n Wed, 28 Mar 2007 01:49:49 +0000\n /dictionary/fran%C3%A7ais/pr%c3%a9f%c3%a8re
注意

從請求派生StringToSign的元素-從字面上URI採取,包括 URL-編碼和大寫。

REST要求簽署問題

當REST要求驗證失敗時,系統會以XML錯誤文件回應要求。此錯誤文件中所包含的資訊是為了協助開發人員診斷問題。特別是 StringToSign 錯誤文件中的 SignatureDoesNotMatch 元素會告訴您系統正在使用的要求標準化。

某些工具包默默地插入您事先不知道的標題,例如Content-Type在PUT. 在大部分情況下,插入的標頭值仍然保持不變,因此您可以使用 Ethereal 或 tcpmon 等工具來探索遺漏的標頭。

查詢字串要求身分驗證替代項

您可以通過將所需信息作為查詢字符串參數傳遞,而不是使用標頭來驗證某些類型的請求。Authorization HTTP這有助於讓第三方瀏覽器直接存取您的私有 Amazon S3 資料,而不需要代理請求。這個想法是構建一個「預先簽名」請求,並將其編碼為最終用戶的URL瀏覽器可以檢索的請求。此外,您可以指定過期時間,限制預先簽章的請求。

如需有關使用查詢參數來驗證請求的詳細資訊,請參閱 Amazon 簡單儲存服務參API考中的驗證請求:使用查詢參數(AWS 簽章版本 4)。如需使用產生預先簽署 AWS SDKs的範例URLs,請參閱使用預先簽署的共用物件 URLs

建立簽章

以下是經過驗證的 Amazon S3 REST 請求的查詢字符串示例。

GET /photos/puppy.jpg ?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Expires=1141889120&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D HTTP/1.1 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com Date: Mon, 26 Mar 2007 19:37:58 +0000

查詢字串要求驗證方法不需要任何特殊HTTP標頭。相反地,必要的身分驗證元素會指定為查詢字串參數。

查詢字串參數名稱 範例值 描述
AWSAccessKeyId AKIAIOSFODNN7EXAMPLE 您的 AWS 存取金鑰 ID。指定用來簽署要求的 AWS 秘密存取金鑰,並間接指定發出要求的開發人員身分。
Expires 1141889120 簽章到期的時間,指定為自紀元以來的秒數 (1970 年 1 月 1 UTC 日 00:00:00)。在此時間 (根據伺服器) 以後收到的要求會遭到拒絕。
Signature vjbyPxybdZaNmGa%2ByT272YEAiv4%3D 的 URL HMAC-SHA1 的 Base64 編碼的編碼。 StringToSign

查詢字串要求身分驗證方法與一般方法稍有不同,但只是 Signature 要求參數與 StringToSign 元素之間的格式不同。下列虛擬語法說明查詢字串要求身分驗證方法。

Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKey, UTF-8-Encoding-Of( StringToSign ) ) ) ); StringToSign = HTTP-VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Expires + "\n" + CanonicalizedAmzHeaders + CanonicalizedResource;

YourSecretAccessKey是 Amazon 在您註冊成為 Amazon 網絡服務開發人員時分配給您的 AWS 秘密訪問密鑰 ID。請注意Signature,URL如何使其適合放置在查詢字串中。另請注意StringToSign,在中,HTTPDate位置元素已被替換為。ExpiresCanonicalizedAmzHeadersCanonicalizedResource 相同。

注意

在查詢字串身分驗證方法中,您不會使用 Datex-amz-date request 標頭來計算 StringToSign。

查詢字串要求身分驗證

請求 StringToSign
GET /photos/puppy.jpg?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE& Signature=NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D& Expires=1175139620 HTTP/1.1 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com
GET\n \n \n 1175139620\n /awsexamplebucket1/photos/puppy.jpg

我們假設當瀏覽器發出GET請求時,它不會提供內容MD5或 Content-Type 標頭,也不會設置任何 x-amz-標頭,因此這些部分保留空白。StringToSign

使用 Base64 編碼

HMAC請求簽名必須以 Base64 編碼。Base64 編碼將簽名轉換為可附加到請求的簡單ASCII字符串。如果在中使用,則必須編碼可能出現在簽名字串中的字元,例如加號 (+)、正斜線 (/) 和 equals (=) URI。例如,如果驗證碼包含加號 (+),請在要求中將它編碼為 %2B。正斜線會編碼為 %2F,而等號則會編碼為 %3D。

如需 Base64 編碼的範例,請參閱 Amazon S3 身分驗證範例