建立已簽署 AWS API的請求 - AWS Identity and Access Management

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

建立已簽署 AWS API的請求

重要

如果您使用 AWS SDK(請參閱範例程式碼和程式庫 ) 或 AWS Command Line Interface (AWS CLI) 工具將API請求傳送至 AWS,您可以略過本節,因為 SDK和 CLI用戶端會使用您提供的存取金鑰來驗證您的請求。除非您有適當的理由拒絕,否則我們建議您一律使用 SDK或 CLI。

在支援多個簽章版本的區域中,手動簽章請求表示您必須指定使用的簽章版本。當您向多區域存取點提供請求時, SDKs CLI會自動切換到使用 Signature 第 4A 版,而不需要其他組態。

您可以使用 AWS SigV4 簽署通訊協定來建立已簽章的 AWS API請求。

  1. 根據請求詳細資訊建立正式請求。

  2. 使用您的 AWS 憑證計算簽章。

  3. 將此簽章新增至請求作為授權標頭。

AWS 然後複寫此程序,並驗證簽章、授予或拒絕相應存取。

若要了解如何使用 AWS SigV4 簽署API請求,請參閱 請求簽章範例

下圖說明 SigV4 簽署程序,包括您為簽署建立之字串的各種元件。

正式請求、要簽署的字串、簽署金鑰和簽章的部分的影像。

下表描述圖表中顯示的函數。您需要為這些函數實作程式碼。如需詳細資訊,請參閱中的程式碼範例 AWS SDKs

函式 描述

Lowercase()

將字串轉換成小寫。

Hex()

小寫基數 16 編碼。

SHA256Hash()

安全雜湊演算法 (SHA) 密碼編譯雜湊函數。

HMAC-SHA256()

HMAC 使用SHA256演算法搭配提供的簽署金鑰進行運算。這是最後的簽章。

Trim()

移除任何前置和結尾空格。

UriEncode()

URI 編碼每個位元組。 UriEncode() 必須強制執行下列規則:

  • URI 編碼未保留字元以外的每個位元組:'A'-'Z'、'a'-'z'、'0'-'9'、'-'、'.'、'_' 和 '~'。

  • 空格字元是預留字元,必須編碼為 "%20" (而不是 "+")。

  • 每個URI編碼位元組由 '%' 和位元組的兩位數十六進位值形成。

  • 十六進位值中的字母必須為大寫,例如 "%1A"。

  • 對所有位置的正斜線字元 '/' 進行編碼 (物件索引鍵名稱除外)。例如,如果物件索引鍵名稱為 photos/Jan/sample.jpg,則不會對索引鍵名稱中的正斜線進行編碼。

重要

您的開發平台提供的標準 UriEncode 函數可能無法運作,因為基礎 的實作和相關不明確性不同RFCs。我們建議您編寫自己的自訂 UriEncode 函數,以確保編碼能夠正常運作。

若要查看 Java 中 UriEncode 函數的範例,請參閱 GitHub 網站上的 Java Utilities

注意

簽署請求時,您可以使用 AWS Signature 第 4 AWS 版或 Signature 第 4A 版。兩者之間的主要差異取決於簽章的計算方式。使用 AWS Signature 第 4A 版 時,簽章不包含區域特定資訊,並使用AWS 4-ECDSA-P256-SHA256演算法計算。

使用臨時安全憑證簽署請求

您可以使用 AWS Security Token Service () 提供的臨時安全憑證,而不是使用長期憑證來簽署請求AWS STS。

使用臨時安全憑證時,您必須X-Amz-Security-Token新增至授權標頭,或將其包含在查詢字串中,以保留工作階段權杖。某些服務會要求您將 X-Amz-Security-Token 新增至正式請求。其他服務只需要您在計算簽章之後於結尾新增 X-Amz-Security-Token。檢查每個 的文件 AWS 服務 ,了解特定要求。

簽署步驟摘要

建立正式請求:

將您的請求內容 (主機、動作、標頭等) 編排為標準正式格式。正式請求是用來建立要簽署之字串的輸入之一。如需建立正式請求的詳細資訊,請參閱 請求簽章的 AWS API元素

建立正式請求的雜湊

使用您用來建立承載雜湊的相同演算法雜湊正式請求。正式請求的雜湊是小寫十六進位字元字串。

建立要簽署的字串

建立字串以簽署正式請求和其他資訊,例如演算法、請求日期、憑證範圍和正式請求的雜湊。

衍生簽署金鑰

在請求日期、區域和服務上執行連續的鍵控雜湊操作 (HMAC),您的 AWS 秘密存取金鑰是初始雜湊操作的金鑰。

計算簽章

在字串上執行鍵控雜湊操作 (HMAC),以使用衍生的簽署金鑰作為雜湊金鑰來簽署。

將簽章新增至請求

將計算的簽章新增至請求的HTTP標頭或查詢字串。

建立正式請求

若要建立標準請求,請將下列字串串連,並以新行字元分隔。這有助於確保您計算的簽章與 AWS 計算的簽章相符。

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>
  • HTTPMethod – HTTP方法,例如 GETHEADPUTDELETE

  • CanonicalUri – 絕對路徑元件 的 URI編碼版本URI,從網域名稱後面/的 開始,直到字串結尾,如果您有查詢字串參數,則到問號字元 (?)。如果絕對路徑為空,請使用正斜線字元 (/)。URI 下列範例中的 是絕對路徑/amzn-s3-demo-bucket/myphoto.jpg,而您不會在絕對路徑/中編碼 :

    http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  • CanonicalQueryString – 編碼URI的查詢字串參數。URI- 個別編碼每個名稱和值。您還必須依索引鍵名稱的字母順序來排序正式查詢字串中的參數。編碼後進行排序。下列URI範例中的查詢字串為:

    http://s3.amazonaws.com/amzn-s3-demo-bucket?prefix=somePrefix&marker=someMarker&max-keys=2

    正式查詢字串如下所示 (為了便於閱讀,向此範例新增了分行符號):

    UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")

    當請求鎖定子資源時,對應的查詢參數值將為空字串 ("")。例如,下列 URI會識別amzn-s3-demo-bucket儲存貯體上的ACL子資源:

    http://s3.amazonaws.com/amzn-s3-demo-bucket?acl

    在這種情況下, CanonicalQueryString 會是:

    UriEncode("acl") + "=" + ""

    如果 URI 不包含 ?,則請求中沒有查詢字串,並將標準查詢字串設定為空字串 ("")。您仍然需要包含新行字元 ("\n")。

  • CanonicalHeaders – 包含其值的請求標頭清單。個別標頭名稱和值對會以新行字元 ("\n") 分隔。以下是 的範例 CanonicalHeader:

    Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n" Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n" ... Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"

    CanonicalHeaders 清單必須包含下列項目:

    • HTTP host 標頭。

    • 如果請求中有 Content-Type 標頭,您必須將其新增至 CanonicalHeaders 清單。

    • 還必須新增您計劃包含在請求中的任何 x-amz-* 標頭。例如,如果您使用的是暫時安全憑證,需要將 x-amz-security-token 包含在您的請求中。您必須在 清單中新增此標頭 CanonicalHeaders.

    注意

    Amazon S3 AWS 請求需要x-amz-content-sha256標頭。其提供請求承載的雜湊。如果沒有承載,您必須提供空字串的雜湊。

    每個標頭名稱必須:

    • 使用小寫字元。

    • 依字母順序顯示。

    • 後面接著冒號 (:)。

    對於值,您必須:

    • 修剪任何前置或結尾空格。

    • 將連續空格轉換為單一空格。

    • 使用逗號分隔多值標頭的值。

    • 您必須在簽章中包含主機標頭 (HTTP/1.1) 或 :authority 標頭 (HTTP/2) 和任何x-amz-*標頭。可以選擇性地在簽章中包含其他標準標頭,例如 content-type。

    本範例中使用的 Lowercase()Trim() 函數在上一節中進行了描述。

    以下是 CanonicalHeaders 字串範例。標頭名稱為小寫且已排序。

    host:s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130708T220855Z

    注意

    對於計算授權簽章而言,僅需要主機和任何 x-amz-* 標頭;但是,為了防止資料竄改,您應考慮在簽章計算中包含所有標頭。

  • SignedHeaders – 按字母順序排序的分號分隔小寫請求標頭名稱清單。清單中的請求標頭與您在 CanonicalHeaders 字串中包含的標頭相同。對於上一個範例, 的值為 SignedHeaders 如下所示:

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload – 使用HTTP請求內文中的承載建立的字串,作為雜湊函數的輸入。此字串使用小寫十六進位字元。

    Hex(SHA256Hash(<payload>>))

    如果請求中沒有承載,您會計算空字串的雜湊,例如當您使用GET請求擷取物件時,承載中沒有任何物件。

    Hex(SHA256Hash(""))
    注意

    對於 Amazon S3,在建構標準請求UNSIGNED-PAYLOAD時包含文字字串,並在傳送請求時設定與x-amz-content-sha256標頭值相同的值。

    Hex(SHA256Hash("UNSIGNED-PAYLOAD"))

建立正式請求的雜湊

使用與您用來建立承載雜湊相同的演算法,建立正式請求的雜湊 (摘要)。正式請求的雜湊是小寫十六進位字元字串。

建立要簽署的字串

若要建立要簽署的字串,請將下列字串串連,並以新行字元分隔。請勿以換行符號字元結束此字串。

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithm – 用來建立標準請求雜湊的演算法。對於 SHA-256,演算法為 AWS4-HMAC-SHA256

  • RequestDateTime – 憑證範圍中使用的日期和時間。此值是 8601 格式的目前UTC時間 ISO (例如 20130524T000000Z)。

  • CredentialScope – 憑證範圍,將產生的簽章限制為指定的區域和服務。字串具有下列格式:YYYYMMDD/region/service/aws4_request。

  • HashedCanonicalRequest – 標準請求的雜湊,在上一個步驟中計算。

以下是登入字串範例。

"AWS4-HMAC-SHA256" + "\n" + timeStampISO8601Format + "\n" + <Scope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))

衍生簽署金鑰

若要衍生簽署金鑰,請在請求日期、區域和服務上執行連續的鍵控雜湊操作 (HMAC),並將 AWS 秘密存取金鑰作為初始雜湊操作的金鑰。

對於每個步驟,使用所需金鑰和資料呼叫雜湊函數。對雜湊函數的每次呼叫結果都會變成雜湊函數的下一次呼叫輸入。

下列範例顯示如何衍生此程序下一節SigningKey中使用的 ,顯示您輸入串連和雜湊的順序。 HMAC-SHA256是用於雜湊資料的雜湊函數,如下所示。

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
需要輸入
  • Key,一個字串,其中包含您的秘密存取金鑰。

  • Date,此字串包含憑證範圍中使用的日期,格式為 YYYYMMDD

  • Region,包含區域代碼的字串 (例如 us-east-1)。

    如需區域字串的清單,請參閱 中的區域端點AWS 一般參考

  • Service,包含服務代碼的字串 (例如 ec2)。

  • 在之前步驟中建立的登入字串。

若要衍生簽署金鑰
  1. 串連"AWS4"和秘密存取金鑰。呼叫雜湊函數,將串連的字串作為索引鍵,日期字串做為資料。

    DateKey = hash("AWS4" + Key, Date)
  2. 呼叫雜湊函數,將上一次呼叫的結果作為索引鍵,區域字串作為資料。

    DateRegionKey = hash(kDate, Region)
  3. 呼叫雜湊函數,將上一次呼叫的結果作為索引鍵,服務字串作為資料。

    服務代碼由 服務定義。您可以使用AWS 定價CLI中的 get-products 來傳回服務的服務代碼。

    DateRegionServiceKey = hash(kRegion, Service)
  4. 呼叫雜湊函數,將上一次呼叫的結果作為索引鍵,"aws4_request" 作為資料。

    SigningKey = hash(kService, "aws4_request")

計算簽章

衍生簽署金鑰後,請在要簽署的字串上執行鍵控雜湊操作來計算簽章。使用衍生的金鑰做為此操作的雜湊金鑰。

計算簽章
  1. 呼叫雜湊函數,將上一次呼叫的結果作為索引鍵,登入字串作為資料。結果是作為二進位值的簽章。

    signature = hash(SigningKey, string-to-sign)
  2. 將簽章的表示形式從二進位轉換為十六進位,使用小寫字元。

將簽章新增至請求

將計算的簽章新增至您的請求。

範例:授權標頭

以下範例顯示針對 DescribeInstances 動作的 Authorization 標頭。為了便於閱讀,此範例使用換行符號進行格式化。在代碼中,這必須是一個連續字串。演算法和 Credential 之間沒有逗號。但是,必須使用逗號分隔其他元素。

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
範例:查詢字串中包含身分驗證參數的請求

以下範例顯示針對 DescribeInstances 動作的查詢,其中包含身分驗證資訊。為了可讀性,此範例已格式化為換行,且未URL編碼。在您的程式碼中,查詢字串必須是URL編碼的連續字串。

https://ec2.amazonaws.com/? Action=DescribeInstances& Version=2016-11-15& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request& X-Amz-Date=20220830T123600Z& X-Amz-SignedHeaders=host;x-amz-date& X-Amz-Signature=calculated-signature