簽署與驗證 REST 要求 - Amazon Simple Storage Service

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

簽署與驗證 REST 要求

注意

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

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

注意

本節中的內容並不適用於 HTTP POST。如需詳細資訊,請參閱「使用 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 取得暫時性安全登入資料時,回應會包含暫時性安全登入資料與工作階段字符。當您將請求傳送至 Amazon S3 時,您會在 x-amz-security-token 標頭中提供此工作階段字符值。如需 IAM 提供之 AWS Security Token Service API 的相關資訊,請移至《AWS Security Token Service API 參考指南》中的 Action (動作)

Authentication 標頭

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

Authorization: AWS AWSAccessKeyId:Signature

當開發人員註冊時,系統會將 AWS 存取金鑰 ID 與 AWS 私密存取金鑰核發給他們。進行要求身分驗證時,AWSAccessKeyId 元素會識別用來計算簽章的存取金鑰 ID;間接來說,就是提出要求的開發人員。

Signature 元素是要求中所選元素的 RFC 2104 HMAC-SHA1,因此 Authorization 標頭的 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 是 RFC 2104 - Keyed-Hashing for Message Authentication 所定義的演算法。該演算法接受兩個位元組字串、一個金鑰與一則訊息的輸入。進行 Amazon S3 請求身分驗證時,請使用您的 AWS 私密存取金鑰 (YourSecretAccessKey) 作為金鑰,並使用 UTF-8 編碼的 StringToSign 作為訊息。HMAC-SHA1 的輸出也是位元組字串,稱為 Digest。Signature 要求參數是由編碼此 Digest 的 Base64 所建構。

將要求標準化以供簽署

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

構建元素 CanonicalizedResource

CanonicalizedResource 代表所要請求的 Amazon S3 資源。您可以透過下列方式針對 REST 要求建構此元素:

1

從空字串 ("") 開始。

2

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

針對虛擬託管型請求 "https://awsexamplebucket1.s3.us-west-1.amazonaws.com/photos/puppy.jpg",CanonicalizedResource 會是 "/awsexamplebucket1"。

針對路徑型請求 "https://s3.us-west-1.amazonaws.com/awsexamplebucket1/photos/puppy.jpg",CanonicalizedResource 會是 ""。

3

附加未解碼之 HTTP 要求 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 Service),請附加 "/"。

4

如果請求定址一項子資源 (例如 ?versioning?location?acl?lifecycle?versionid),請附加該子資源、其值 (若有) 與問號。請注意,如有多項子資源,則必須按詞典編纂方式依子資源名稱排序並以 '&' 分隔,例如 ?acl&versionId=value

構建 CanonicalizedResource 元素時必須包含的子資源是 ACL,生命週期,位置,日誌記錄,通知,partNumber,策略,requestPayment,UpLoaDid,uploadId,versionId,版本,版本和網站。

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

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

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

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

構建元素 CanonicalizedAmzHeaders

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

1 將每個 HTTP 標頭名稱轉換成小寫。例如,'X-Amz-Date' 會變成 'x-amz-date'。
2 按詞典編纂方式依標頭名稱排序標頭集合。
3 按照 RFC 2616 第 4.2 節規定將具有相同名稱的標題字段合併為一個「標題名稱:comma-separated-value-list」對,值之間沒有任何空格。例如,兩個中繼資料標頭 '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 的前幾個標頭元素 (Content-Type、日期和 Content-MD5) 屬於位置性標頭。StringToSign 不包含這些標頭的名稱,僅包含其在請求中的值。相對的,'x-amz-' 元素是具名的。其標頭名稱與標頭值都會出現在 StringToSign 中。

如果 StringToSign 定義中所需的位置性標頭不會出現在您的要求中 (例如 Content-TypeContent-MD5 對 PUT 要求為選用但對 GET 要求則沒有意義),請以空字串 ("") 取代該位置。

時間戳記需求

經過驗證的要求必須具有有效的時間戳記 (使用 HTTP Date 標頭或 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。如需範例,請參閱下一節。

身分驗證範例

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

參數
AWSAccessKeyId AKIAIOSFODNN7EXAMPLE
AWSSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

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

Object 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()}")

Object 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-MD5 HTTP 實體標頭會出現在 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
注意

衍生自要求 URI 的 StringToSign 元素必須依原狀採用,包括 URL 編碼與大寫。

REST 要求簽署問題

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

某些工具組會在您事先不知情的情況下,以無訊息方式插入標頭,例如在 PUT 期間加入標頭 Content-Type。在大部分情況下,插入的標頭值仍然保持不變,因此您可以使用 Ethereal 或 tcpmon 等工具來探索遺漏的標頭。

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

您可以將必要資訊當作查詢字串參數來傳遞,以驗證特定類型的要求,而不是使用 Authorization HTTP 標頭。這有助於讓第三方瀏覽器直接存取您的私有 Amazon S3 資料,而不需要代理請求。此概念是建構「預先簽章」的請求,然後將其編碼為最終使用者可以擷取的 URL。此外,您可以指定過期時間,限制預先簽章的請求。

如需有關使用查詢參數來驗證請求的詳細資訊,請參閱《Amazon Simple Storage Service API 參考》中的對請求進行身分驗證:使用查詢參數 (AWS Signature 第 4 版)。關於使用 AWS 開發套件產生預先簽章 URL 的範例,請參閱「使用預先簽章的 URL 來共用物件」。

建立簽章

以下為經過查詢字串驗證的 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 簽章的過期時間,指定為自 epoch (1970 年 1 月 1 日 00:00:00 UTC) 起經過的秒數。在此時間 (根據伺服器) 以後收到的要求會遭到拒絕。
Signature vjbyPxybdZaNmGa%2ByT272YEAiv4%3D 的 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 Web Services 開發人員時,由 Amazon 指派給您的 AWS 私密存取金鑰 ID。請注意 Signature 如何經過 URL 編碼,以便適當放在查詢字串中。另請注意,在 StringToSign 中,HTTP Date 位置性元素已取代為 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 要求時未提供 Content-MD5 或 Content-Type 標頭,也未設定任何 x-amz- 標頭,因此 StringToSign 的這些部分會保留空白。

使用 Base64 編碼

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

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