本頁內容適用於 Apigee 和 Apigee Hybrid。
查看
Apigee Edge 說明文件。
這項政策會計算雜湊式訊息驗證碼 (HMAC),並視需要進行驗證。HMAC 有時也稱為「金鑰訊息驗證碼」或「金鑰雜湊」,會使用加密編譯雜湊函式 (例如 SHA-1、SHA-224、SHA-256、SHA-384、SHA-512 或 MD-5) 處理「訊息」和密鑰,在該訊息上產生簽名或訊息驗證碼。這裡的「訊息」是指任何位元組串流。一般來說,訊息的傳送者會將訊息和 HMAC 傳送給接收者,而接收者可以使用 HMAC 和共用私密金鑰驗證訊息。
這項政策屬於標準政策,可部署至任何環境類型。如要瞭解各環境類型適用的政策類型和可用性,請參閱「政策類型」。
如要進一步瞭解 HMAC,請參閱「HMAC:訊息驗證的鍵控雜湊 (rfc2104)」。
範例
生成 HMAC
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base64' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template, which means the "message" the policy operates on can include fixed and multiple variable parts, including newlines and static functions. Whitespace, such as newlines and space characters, is significant. --> <Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce}</Message> <!-- default encoding is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
驗證 HMAC
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base16' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template. This policy verifies an HMAC on the request content. --> <Message>{request.content}</Message> <!-- VerificationValue is optional. Include it to perform an HMAC check. --> <VerificationValue encoding='base16' ref='expected_hmac_value'/> <!-- default encoding of the output is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
簽章的計算和驗證程序完全相同。HMAC 政策會計算 HMAC,並可選擇性地根據預期值驗證計算出的簽章。選用的 VerificationValue
元素 (如有) 會指示政策根據已知或指定的值檢查計算值。
HMAC 的元素參照
政策參考資料說明 HMAC 政策的元素和屬性。
適用於頂層元素的屬性
<HMAC name="HMAC" continueOnError="false" enabled="true" async="false">
所有政策父項元素都有下列屬性。
屬性 | 說明 | 預設 | 外觀狀態 |
---|---|---|---|
名稱 |
政策的內部名稱。名稱只能使用以下字元:
A-Z0-9._\-$ % 。不過,Apigee 使用者介面會強制執行其他限制,例如自動移除非英數字元。
(選用) 使用 |
不適用 | 必填 |
continueOnError |
設為 false ,以便在政策失敗時傳回錯誤。這是大多數政策的預期行為。
設為 |
false | 選用 |
已啟用 |
設為 true 即可強制執行政策。
設為 |
是 | 選用 |
非同步 | 這項屬性已淘汰。 | false | 已淘汰 |
<Algorithm>
<Algorithm>algorithm-name</Algorithm>
指定計算 HMAC 時要使用的雜湊演算法。
預設 | 不適用 |
外觀狀態 | 必填 |
類型 | 字串 |
有效值 | SHA-1 、SHA-224 、SHA-256 、SHA-384 、
SHA-512 和 MD-5
政策設定接受演算法名稱,不區分大小寫,且字母和數字之間可有連字號,也可沒有。舉例來說, |
<DisplayName>
<DisplayName>Policy Display Name</DisplayName>
除了名稱屬性之外,您也可以使用這個屬性,在 Apigee UI 代理項目編輯器中,以其他自然語言名稱標示政策。
預設 | 如果省略這個元素,系統會使用政策名稱屬性的值。 |
外觀狀態 | 選用 |
類型 | 字串 |
<Message>
<Message>message_template_here</Message> or <Message ref='variable_here'/>
指定要簽署的訊息酬載。這個元素的輸入內容支援 訊息範本 (變數替換),可在執行階段加入其他項目,例如時間戳記、隨機數、標頭清單或其他資訊。例如:
<Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce} </Message>
訊息範本可包含固定和可變動的部分,包括換行符號和靜態函式。 空白字元 (例如換行符號和空格字元) 具有意義。
預設 | 不適用 |
外觀狀態 | 必填 |
類型 | 字串 |
有效值 | 文字值可使用任何字串。如果提供 ref 屬性,系統會優先採用該屬性,而非文字值。政策會將文字值或參照變數評估為訊息範本。 |
<Output>
<Output encoding='encoding_name'>variable_name</Output>
指定政策應使用計算出的 HMAC 值設定的變數名稱。 並指定輸出內容要使用的編碼。
預設 |
預設輸出變數為 |
外觀狀態 | (選用步驟) 如果沒有這個元素,政策會設定流程變數 hmac.POLICYNAME.output ,並採用 Base64 編碼值。 |
類型 | 字串 |
有效值 | 編碼時,請使用 這些值不區分大小寫;
|
<SecretKey>
<SecretKey encoding='encoding_name' ref='private.secretkey'/>
指定用於計算 HMAC 的密鑰。這個鍵是從參照的變數取得,並根據特定編碼解碼。
預設 |
參照變數沒有預設值,因此必須提供 如果沒有 |
外觀狀態 | 必填 |
類型 | 字串 |
有效值 |
使用編碼屬性可指定包含 UTF-8 可列印字元範圍以外位元組的鍵。舉例來說,假設政策設定包含以下內容: <SecretKey encoding='hex' ref='private.encodedsecretkey'/>
假設
在本例中,金鑰位元組會解碼為:[53 65 63 72 65 74 31 32 33]
(每個位元組都以十六進位表示)。再舉一例,如果使用 |
<VerificationValue>
<VerificationValue encoding='encoding_name' ref='variable_name'/> or <VerificationValue encoding='encoding_name'>string_value</VerificationValue>
(選用) 指定驗證值,以及用於編碼驗證值的編碼方式。政策會使用這項編碼解碼值。
預設 | 沒有預設驗證值。如果存在這個元素,但缺少 encoding 屬性,政策會使用 base64 的預設編碼 |
外觀狀態 | 選用 |
類型 | 字串 |
有效值 |
編碼屬性的有效值為:
|
<IgnoreUnresolvedVariables>
<IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables>
如果政策中指定的任何參照變數無法解析,請設為 false
,讓政策擲回錯誤。設為 true
,將任何無法解析的變數視為空字串 (空值)。
IgnoreUnresolvedVariables 布林值只會影響訊息範本參照的變數。SecretKey
和 VerificationValue
都可以參照變數,但兩者都需要可解析,因此 ignore
設定不適用於這些變數。
預設 | 否 |
外觀狀態 | 選用 |
類型 | 布林值 |
有效值 | true 或 false |
流程變數
政策可在執行期間設定這些變數。
變數 | 說明 | 範例 |
---|---|---|
hmac.policy_name.message |
這項政策會使用有效訊息設定這個變數,也就是評估 Message 元素中指定訊息範本的結果。 |
hmac.HMAC-Policy.message = "Hello, World" |
hmac.policy_name.output |
當 Output 元素未指定變數名稱時,取得 HMAC 計算結果。 |
hmac.HMAC-Policy.output = /yyRjydfP+fBHTwXFgc5AZhLAg2kwCri+e35girrGw4= |
hmac.policy_name.outputencoding |
取得輸出編碼的名稱。 | hmac.HMAC-Policy.outputencoding = base64 |
一般問題
從某個層面來看,HMAC 政策似乎很簡單:提供金鑰和訊息,即可在回應中取得計算出的 HMAC。如果您為已知的訊息和金鑰組合取得非預期的 HMAC 值,使用這項政策時可能會感到困擾。本節將說明一些使用注意事項,協助您解決這類問題。
驗證期間發生 HMAC 不符的情況,通常有兩個常見原因:訊息中的空白字元差異,以及編碼和解碼差異。後者適用於 SecretKey
元素和 Output
元素。
空白字元差異
對人類而言可能微不足道的差異,卻會影響輸出的 HMAC 值。舉例來說,假設可表示為「Secret123」的密鑰。使用 UTF-8 解碼時,金鑰位元組會是:[53 65 63 72 65 74 31 32 33]
。使用該金鑰計算訊息 abc
的 HMAC-SHA256,會產生 a7938720fe5749d31076e6961360364c0cd271443f1b580779932c244293bc94
。在訊息中加入單一空格,使訊息變成 abc<SPACE>
,其中 <SPACE>
代表 ASCII 32,會產生 274669b2a85d2532da48e2ce3d8e52ee17346d1bcd1a606d87db1934b5ab294b
的 HMAC-SHA256。
同樣地,如果訊息是 abc<NEWLINE>
,其中 <NEWLINE>
代表 ASCII 10,則 HMAC 為 0780370844ca07f896066837e8230d3b6a775f678a4ae03e6b5e864c674831f5
。訊息的微幅變更會產生大不相同的 HMAC 值。這是正常的。
這是 HMAC 的預期行為。
重點:請務必確保用於計算原始 HMAC 的郵件內文,與用於驗證 HMAC 的郵件內文完全相同。如果 HMAC 驗證者以任何方式變更訊息酬載 (例如新增任何空白字元或重新格式化文字),計算出的 HMAC 就會變更。
在政策設定中使用訊息範本時,請特別留意。舉例來說,這段政策設定片段顯示潛在問題:
<HMAC name='HMAC-1'> ... <!-- the result of this message template will include surrounding whitespace --> <Message> {request.content} </Message> ... </HMAC>
在 <Message>
元素中評估訊息範本的結果,會包含訊息內容周圍的換行符和空格。這可能不是預期的結果。較好的設定如下:
<HMAC name='HMAC-1'> ... <Message>{request.content}</Message> ... </HMAC>
編碼差異
以不同方式解碼同一組金鑰材料,會產生不同的金鑰。假設密鑰可表示為「U2VjcmV0S2V5MTIz」。使用 UTF-8 解碼時,以 base16 表示的鍵位元組為:[55 32 56 6a 63 6d 56 30 53 32 56 35 4d 54 49 7a]
。經過 base64 解碼後,金鑰位元組會是 [53 65 63 72 65 74 4b 65 79 31 32 33]
。以不同方式解碼來源資料會產生不同的金鑰,進而產生不同的 HMAC 值。
重點:請務必確保用於計算原始 HMAC 的金鑰內容,與用於驗證 HMAC 的金鑰完全相同。這可能表示要確保兩端都使用相同的金鑰編碼。在 HMAC 政策中,您可以在 SecretKey
元素上使用 encoding
屬性,指定金鑰編碼。
也請考慮輸出內容的編碼。以 base16 或十六進位編碼表示的 HMAC-SHA256 (27f17e11c8ece93844c5eb5e55161d993368628a214f9a51c25d0185e8ea06e2
) 與以 base64 編碼形式表示的 HMAC-SHA256 (J/F+Ecjs6ThExeteVRYdmTNoYoohT5pRwl0BhejqBuI=
) 相同。這兩個字串看起來不同,但代表相同的值。請務必使用相同的編碼方式,編碼原始計算的 HMAC 和驗證 HMAC。在 HMAC 政策中,您可以在 Output
元素上使用 encoding
屬性,指定所需的輸出編碼,並在 VerificationValue
元素上使用相同屬性,指定如何解碼驗證者。
錯誤參考資料
本節說明這項政策觸發錯誤時,Apigee 傳回的錯誤代碼和錯誤訊息,以及 Apigee 設定的錯誤變數。如果您要開發錯誤處理規則,就必須瞭解這項資訊。如需更多資訊,請參閱「關於政策錯誤的相關資訊」和「處理錯誤」。
執行階段錯誤
政策執行時可能會發生這些錯誤。
錯誤代碼 | HTTP 狀態 | 發生時機 |
---|---|---|
steps.hmac.UnresolvedVariable |
401 | 如果 HMAC 政策中指定的變數為下列任一情況,就會發生這項錯誤:
|
steps.hmac.HmacVerificationFailed |
401 | HMAC 驗證失敗;提供的驗證值與計算值不符。 |
steps.hmac.HmacCalculationFailed |
401 | 政策無法計算雜湊式訊息驗證碼 (HMAC)。 |
steps.hmac.EmptySecretKey |
401 | 密鑰變數的值為空白。 |
steps.hmac.EmptyVerificationValue |
401 | 儲存驗證值的變數為空白。 |
部署錯誤
部署含有這項政策的 Proxy 時,可能會發生這些錯誤。
錯誤名稱 | HTTP 狀態 | 發生時機 |
---|---|---|
steps.hmac.MissingConfigurationElement |
401 | 缺少必要元素或屬性時,就會發生這項錯誤。 |
steps.hmac.InvalidValueForElement |
401 | 如果 Algorithm 元素中指定的值不是下列任一值:SHA-1 、SHA-224 、SHA-256 、SHA-512 或 MD-5 ,就會發生此錯誤。 |
steps.hmac.InvalidSecretInConfig |
401 | 如果為 SecretKey 明確提供文字值,就會發生這個錯誤。 |
steps.hmac.InvalidVariableName |
401 | 如果 SecretKey 變數不含 private 前置字串 (private. ),就會發生這個錯誤。 |
錯誤變數
系統會在發生執行階段錯誤時設定這些變數。如需更多資訊 請參閱注意事項 政策錯誤。
變數 | 地點 | 範例 |
---|---|---|
fault.name="fault_name" |
fault_name 是錯誤的名稱,如 上方的「執行階段錯誤」表格。錯誤名稱是最後一個 部分錯誤 | fault.name Matches "UnresolvedVariable" |
hmac.policy_name.failed |
這項政策會在發生錯誤時設定這個變數。 | hmac.HMAC-Policy.failed = true |
錯誤回應範例
針對錯誤處理,最佳做法是將錯誤的 errorcode
部分加以包裝
回應。請勿參考 faultstring
中的文字,因為可能會變動。
錯誤規則範例
<FaultRules> <FaultRule name="HMAC Policy Errors"> <Step> <Name>AM-Unauthorized</Name> <Condition>(fault.name Matches "HmacVerificationFailed")</Condition> </Step> <Condition>hmac.HMAC-1.failed = true</Condition> </FaultRule> </FaultRules>