apisix~hmac-auth插件的使用
hmac-auth插件需要和 Consumer 一起使用,API 的使用者必須將密匙添加到請求頭中以驗證其請求,下面介紹它的主要用法
參數(shù)
- algorithm 算法 默認(rèn)hmac-sha256 ["hmac-sha1", "hmac-sha256", "hmac-sha512"],客戶端請求頭X-HMAC-ALGORITHM=hmac-sha256
- clock_skew 簽名允許的時間偏移(以秒為單位)
- access_key Consumer 的 access_key 必須是唯一的,客戶端請求時在請求頭添加X-HMAC-ACCESS-KEY=access_key值
- signed_headers 要在加密計算中使用的 headers 列表,客戶端請求頭X-HMAC-SIGNED-HEADERS
- X-HMAC-SIGNATURE 客戶端請求頭中的簽名
消費(fèi)者配置
- 添加hmac-auth插件,配置access_key,類似于app_id
- 這個消費(fèi)者有兩個能力,除了hmac-auth以外,還有key-auth的能力,即簡單的認(rèn)證方式

簽名生成的過程
接下來,我們將以下述請求為例,為你介紹簽名生成公式的具體計算過程:
curl -i http://127.0.0.1:9080/index.html?name=james&age=36 \
-H "X-HMAC-SIGNED-HEADERS: User-Agent;x-custom-a" \
-H "x-custom-a: test" \
-H "User-Agent: curl/7.29.0"
- 上文請求默認(rèn)的 HTTP Method 是 GET,得到 signing_string 為:
"GET"
- 請求的 URI 是 /index.html,根據(jù) HTTP Method + \n + HTTP URI 得到 signing_string 為:
"GET
/index.html"
- URL 中的 query 項是 name=james&age=36,假設(shè) encode_uri_params 為 false,根據(jù) canonical_query_string 的算法,重點是對 key 進(jìn)行字典排序,得到 age=36&name=james;根據(jù) HTTP Method + \n + HTTP URI + \n + canonical_query_string 得到 signing_string 為:
"GET
/index.html
age=36&name=james"
- access_key 是 user-key,根據(jù) HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key 得到 signing_string 為:
"GET
/index.html
age=36&name=james
user-key"
- Date 是指
GMT格式的日期,不能缺少,形如 Tue, 19 Jan 2021 11:33:20 GMT, 根據(jù) HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key + \n + Date 得到 signing_string 為:
"GET
/index.html
age=36&name=james
user-key
Tue, 19 Jan 2021 11:33:20 GMT"
因為人家apisix服務(wù)端lua插件源碼,使用的是這種GMT格式,所以咱們使用者也需要跟人家保持一致,事實上,我更傾向于使用時間戳,沒有日期格式和時區(qū)的問題

- signed_headers_string 用來制定參與到簽名的 headers,在上面示例中包括 User-Agent: curl/7.29.0 和 x-custom-a: test。
根據(jù) HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key + \n + Date + \n + signed_headers_string + \n,得到完整的 signing_string 為:
"GET
/index.html
age=36&name=james
user-key
Tue, 19 Jan 2021 11:33:20 GMT
User-Agent:curl/7.29.0
x-custom-a:test
"
Body請求體校驗
當(dāng) validate_request_body 設(shè)置為 true 時,插件將計算請求 body 的 hmac-sha 值,并與請求 headers 中的 X-HMAC-DIGEST 的值進(jìn)行校驗。
X-HMAC-DIGEST: base64(hmac-sha())
X-HMAC-DIGEST: base64(hmac-sha(<body>))
如果沒有請求 body,你可以將 X-HMAC-DIGEST 的值設(shè)置為空字符串的 HMAC-SHA。
注意:
當(dāng)開啟 body 校驗時,為了計算請求 body 的 hmac-sha 值,該插件會把 body 加載到內(nèi)存中,在請求 body 較大的情況下,可能會造成較高的內(nèi)存消耗。
為了避免這種情況,你可以通過設(shè)置 max_req_body(默認(rèn)值是 512KB)配置項來配置最大允許的 body 大小,body 超過此大小的請求會被拒絕。
測試插件
假設(shè)當(dāng)前請求為:
curl -i http://127.0.0.1:9080/index.html?name=james&age=36 \
-H "X-HMAC-SIGNED-HEADERS: User-Agent;x-custom-a" \
-H "x-custom-a: test" \
-H "User-Agent: curl/7.29.0"
通過以下 Python 代碼為上述請求生成簽名 SIGNATURE:
import base64
import hashlib
import hmac
secret = bytes('my-secret-key', 'utf-8')
message = bytes("""GET
/index.html
age=36&name=james
user-key
Tue, 19 Jan 2021 11:33:20 GMT
User-Agent:curl/7.29.0
x-custom-a:test
""", 'utf-8')
hash = hmac.new(secret, message, hashlib.sha256)
# to lowercase base64
print(base64.b64encode(hash.digest()))
| Type | Hash |
|---|---|
| SIGNATURE | 8XV1GB7Tq23OJcoz6wjqTs4ZLxr9DiLoY4PxzScWGYg= |
你也可以參考 Generating HMAC signatures 了解如何使用不同的編程語言生成簽名。
簽名生成后,你可以通過以下示例使用生成的簽名發(fā)起請求:
curl -i "http://127.0.0.1:9080/index.html?name=james&age=36" \
-H "X-HMAC-SIGNATURE: 8XV1GB7Tq23OJcoz6wjqTs4ZLxr9DiLoY4PxzScWGYg=" \
-H "X-HMAC-ALGORITHM: hmac-sha256" \
-H "X-HMAC-ACCESS-KEY: user-key" \
-H "Date: Tue, 19 Jan 2021 11:33:20 GMT" \
-H "X-HMAC-SIGNED-HEADERS: User-Agent;x-custom-a" \
-H "x-custom-a: test" \
-H "User-Agent: curl/7.29.0"
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Tue, 19 Jan 2021 11:33:20 GMT
Server: APISIX/2.2
......
你也可以將簽名放到請求頭 Authorization 字段中:
curl http://127.0.0.1:9080/index.html \
-H 'Authorization: hmac-auth-v1# + ACCESS_KEY + # + base64_encode(SIGNATURE) + # + ALGORITHM + # + DATE + # + SIGNED_HEADERS' -i
postman測試結(jié)果
)
浙公網(wǎng)安備 33010602011771號