2016-04-30 30 views
3

)聲明:這是一個「操作方法」,因爲我在實施AWS簽名版本4時找不到任何CF示例4如何翻譯AWS任務1:爲簽名版本4創建規範請求

如何在CF中實現Task 1: Create a Canonical Request for Signature Version 4

總結:

  1. 開始與HTTP請求方法(GET,PUT,POST等),後跟一個換行符。
  2. 添加規範的URI參數,後跟一個換行符。
  3. 添加規範查詢字符串,後跟換行符
  4. 添加規範標頭,後跟換行符。
  5. 添加簽名的標題,後跟換行符。
  6. 使用散列(摘要)函數(如SHA256)從請求主體中的有效內容創建散列值
  7. 通過將每個步驟的組件作爲單個字符串進行組合,構建完成的規範請求。
  8. 使用用於散列負載的相同算法創建規範請求的摘要(散列)。

回答

4

下面是一個CFSCRIPT實施Task 1: Create a Canonical Request for Signature Version 4

結果:

f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59 

代碼:

  1. 開始與HTTP請求方法(GET,PUT POST等)

    requestMethod = "GET"; 
    writeOutput("<br>requestMethod: <code>"& requestMethod &"</code>"); 
    
  2. 添加(編碼)標準URI參數,接着一個換行符。

    originalURI = ""; 
    // If the absolute path is empty, use a forward slash (/) 
    originalURI = len(trim(originalURI)) ? originalURI : "/"& originalURI; 
    // Encode URI and preserve forward slashes 
    canonicalURI = replace(encodeRFC3986(originalURI), "%2F", "/", "all"); 
    writeOutput("<br>canonicalURI: <code>"& canonicalURI &"</code>"); 
    
  3. 添加規範化查詢字符串,後跟一個換行符

    queryParams = { "Action"="ListUsers", "Version"="2010-05-08" }; 
    
    // a) Encode parameter names and values 
    encodedParams = {}; 
    structEach(queryParams, function(key, value) { 
        encodedParams[ encodeRFC3986(arguments.key) ] = encodeRFC3986(arguments.value); 
    }); 
    
    // b) Sort the encoded parameter in ascending order (ASCII order) 
    encodedKeyNames = structKeyArray(encodedParams); 
    arraySort(encodedKeyNames, "text"); 
    
    // c) Build the canonical query string. Starting with first parameter, append encoded 
    // parameter name, followed by character '=' (ASCII code 61), followed by the encoded value 
    encodedPairs = []; 
    for (key in encodedKeyNames) { 
        arrayAppend(encodedPairs, key &"="& encodedParams[ key ]); 
    } 
    // d) Append the character '&' (ASCII code 38) after each parameter value, except for the last value in the list. 
    canonicalQueryString = arrayToList(encodedPairs, "&"); 
    writeOutput("<br>canonicalQueryString: <code>"& canonicalQueryString &"</code>"); 
    
  4. 添加經典頭,跟着一個換行符。

    requestHeaders = { "Content-type"= "application/x-www-form-urlencoded; charset=utf-8" 
            , "Host" = "iam.amazonaws.com" 
            , "X-Amz-Date" = "20150830T123600Z" 
           }; 
    
    // a) Convert all header names to lowercase and remove leading spaces and trailing spaces. 
    // Convert sequential spaces in the header value to a single space.   
    cleanedHeaders = {}; 
    structEach(requestHeaders, function(key, value) { 
        headerName = reReplace(trim(arguments.key), "\s+", " ", "all"); 
        headerValue = reReplace(trim(arguments.value), "\s+", " ", "all"); 
        cleanedHeaders[ lcase(headerName) ] = headerValue; 
    }); 
    
    // b) [sort] the (lowercase) headers by character code 
    sortedHeaderNames = structKeyArray(cleanedHeaders); 
    arraySort(sortedHeaderNames, "text"); 
    
    // c) Append the lowercase header name followed by a colon. 
    // Do not sort the values in headers that have multiple values. 
    cleanedPairs = []; 
    for (key in sortedHeaderNames) { 
        arrayAppend(cleanedPairs, key &":"& cleanedHeaders[ key ]); 
    } 
    
    // d) Append new line after each header pair. Should END WITH a new line 
    canonicalHeaderString = arrayToList(cleanedPairs, chr(10)) & chr(10) ; 
    writeOutput("<br> canonicalHeaderString: <code>"& canonicalHeaderString &"</code>"); 
    
  5. 添加簽名的報頭,然後是換行字符

    // To create the signed headers list, convert all header names to lowercase, 
    // sort them by character code, and use a semicolon to separate the header names. 
    // Note, we already have the sorted names from the canonical header logic (step 4) 
    signedHeaderString = arrayToList(sortedHeaderNames, ";"); 
    writeOutput("<br>signedHeaderString: <code>"& signedHeaderString &"</code>"); 
    
  6. 在HTTP/HTTPS請求的主體中創建淨荷的散列

    requestPayload = ""; 
    payloadChecksum = lcase(hash(requestPayload , "SHA256")); 
    writeOutput("<br>payloadChecksum: <code>"& payloadChecksum &"</code>"); 
    
  7. Con STRUCT規範請求,由所述部件從每個步驟作爲單個字符串

    canonicalRequest = requestMethod & chr(10) 
            & canonicalURI & chr(10) 
            & canonicalQueryString & chr(10) 
            & canonicalHeaderString & chr(10) 
            & signedHeaderString & chr(10) 
            & payloadChecksum ; 
    
    writeOutput("<br>canonicalRequest: <pre>"& canonicalRequest &"</pre>"); 
    
  8. 組合創建具有相同的算法規範請求用於散列有效載荷

    requestDigest = lcase(hash(canonicalRequest , "SHA256")); 
    writeOutput("<br>requestDigest: <code>"& requestDigest &"</code>"); 
    
    的摘要(哈希值)

UDF encodeRFC 3986:

/** 
    * URI encoding per RFC 3986: 
    * <ul> 
    *  <li>Unreserved characters that should not be escaped: ALPHA/DIGIT/"-"/"."/"_"/"~" </li> 
    *  <li>Spaces should be encoded as %20 instead of +</li> 
    *  <li>Reserved characters that should be escaped include: ? ## [ ] @ ! $ & ' () * + , ; =</li> 
    * </ul> 
    * 
    * @text String to encode 
    * @returns URI encoded text 
    */ 
    public function encodeRFC3986(required string text) { 
     // Requires CF10+ 
     Local.encoded = encodeForURL(arguments.text); 

     // Undo encoding of tilde "~" 
     Local.encoded = replace(Local.encoded, "%7E", "~", "all"); 
     // Change space encoding from "+" to "%20" 
     Local.encoded = replace(Local.encoded, "+", "%20", "all"); 
     // URL encode asterisk "*" 
     Local.encoded = replace(Local.encoded, "*", "%2A", "all"); 

     return Local.encoded; 
    } 
相關問題