OpenSearch服務會對每個訪問的請求進行身分識別驗證,通過使用Access Key ID和Access Key Secret進行對稱式加密的方法來驗證請求的寄件者身份。
Access Key ID和Access Key Secret由阿里雲官方頒發給訪問者(可以通過阿里雲官方網站申請和管理),其中Access Key ID用於標識訪問者的身份。
Access Key Secret是用於加密簽名字串和伺服器端驗證簽名字串的密鑰,必須嚴格保密,只有阿里雲和使用者知道。
支援應用類型
進階版
標準版
通訊協定
只支援 HTTP 協議
請求對應方式
搜尋資料必須使用:GET
推送資料必須使用:POST
Authorization 欄位計算方法
需在 HTTP 要求 Header 頭資訊中,添加 Authorization(授權)來包含簽名(Signature)資訊,表明該請求已被授權。請求Header 中也需要包含文檔下面“簽名樣本”部分中“請求Header”中提到的這些相關的請求Header。
請求 Header 中包含的參數都必須要參與簽名(例如 Content-Md5,Content-Type,Date,HTTP專有 Header 等等,同時還需要注意:"Authorization: OPENSEARCH "中OPENSEARCH後面有一個空格)。
"Authorization: OPENSEARCH " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ Content-Md5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedOpenSearchHeaders
+ CanonicalizedResource))
按照RFC2104的定義,使用上面的用於簽名的字串計算簽名HMAC值
簽名的方法用 RFC 2104 中定義的 HMAC-SHA1 方法
簽名的字串必須為UTF-8格式
含有中文字元的簽名字串必須先進行UTF-8編碼,再與AccessKeySecret計算最終簽名
簽名參數先後順序,必須和上面保持一致
參數 | 描述 |
AccessKeyId | 不可為空,請求Header 中的 Authorization 需要用到該 AccessKeyId 值,表示訪問指定應用的使用者 |
AccessKeySecret | 不可為空,簽名所需的密鑰 |
VERB | 不可為空,表示請求操作方法。HTTP 要求 Method,主要有 PUT、GET、POST、HEAD、DELETE 等,不同介面Method也不同 |
\n | 分行符號 |
Content-MD5 | 請求body有內容時,不可為空。該參數值為,請求body 的MD5值。該要求標頭用於訊息合法性的檢查(訊息內容是否與發送時一致),例如 ,對於不發送 body 的請求,例如查詢請求,此值請留空。詳情參看 RFC2616 Content-MD5 |
Content-Type |
|
Date | 不可為空,表示此次操作時間,且必須為 秒級 的 ISO 格式,如 |
CanonicalizedOpenSearchHeaders | 不可為空,用於區分每次請求,以 |
CanonicalizedResource | 不可為空,表示使用者此次請求路徑,例如 |
查詢請求
請求籤名參數 | 必須 | 請求 Header 參數 | 必須 |
AccessKeySecret | 是 | Date | 是 |
VERB | 是 | X-Opensearch-Nonce | 是 |
Date | 是 | Authorization | 是 |
x-opensearch-nonce | 是 | ||
canonicalized_resource | 是 |
Header 中的參數值必須要與對應簽名方法中的參數值一致
建議將 Content-Md5,Content-Type,Date,CanonicalizedOpenSearchHeaders,Authorization 這些參數都添加到請求Header中,只包含必須參數可能會出現報錯,需避免
請求 Header 中包含的參數都必須要參與簽名
推送請求
請求籤名參數 | 必須 | 請求 Header 參數 | 必須 |
AccessKeySecret | 是 | Content-MD5 | 是 |
VERB | 是 | Date | 是 |
Content-MD5 | 是 | Authorization | 是 |
Date | 是 | ||
canonicalized_resource | 是 |
Header 中的參數值必須要與對應簽名方法中的參數值一致
理論上 Content-Md5,Content-Type,Date,CanonicalizedOpenSearchHeaders,Authorization 這些參數都需要添加到請求Header中,只包含必須參數可能會出現報錯,需避免
請求 Header 中包含的參數都必須要參與簽名
構建CanonicalizedOpenSearchHeaders的方法
所有以 X-Opensearch-
為首碼的 HTTP專有 Header 被稱為 CanonicalizedOpenSearchHeaders,其他非 HTTP專有 Header 將不被納入驗證
將所有以
X-Opensearch-
為首碼的HTTP專有 Header 對應的內容補齊,例如X-Opensearch-Nonce : 1551089397451704
(該Nonce參數值,可由10位時間戳記+6位隨機值(100000~999999)組合而成,例如1551089397451704
),再去除所有值為空白的HTTP專有 Header將這些有對應內容值的HTTP專有 Header 按照名稱的字典序進行升序排序
再將這些排序後的專有 Header名,全部轉換成小寫字母,例如將
X-Opensearch-Nonce : 1551089397451704
轉換成x-opensearch-nonce : 1551089397451704
刪除要求標頭和內容之間分隔字元兩端出現的任何空格。例如該
x-opensearch-nonce : 1551089397451704
參數,刪除兩端空格後為:x-opensearch-nonce:1551089397451704
最後將每個要求標頭及對應內容作為一個單位項,再將每一項之間用
\n
串連拼成最後的 CanonicalizedOpenSearchHeaders,注意最後一個也要有\n
若查詢請求Header中不包含此處HTTP專有 Header,即該參數中一個HTTP專有 Header都沒有,則無需 \n,只需在簽名方法中去掉該CanonicalizedOpenSearchHeaders簽名參數即可,該參數不參與簽名計算。
將HTTP專有 Header添加到Header中時,不能是轉換後的小寫形式,需按原格式顯示
構建CanonicalizedResource的方法
簽名的字串必須為UTF-8格式,且含有中文字元的簽名字串必須先進行 UTF-8 編碼,再與 AccessKeySecret 計算最終簽名
查詢 CanonicalizedResource = path + ? + query
推送 CanonicalizedResource = path
構建 path 部分
對 path 進行urlencode後,再替換 %2F
為 /
,下面的app_schema_demo需替換為自己應用程式名稱,常見 path 如下所示
search查詢path
/v3/openapi/apps/app_schema_demo/search
suggest查詢path
/v3/openapi/suggestions/suggestion_name/actions/search
最終查詢指定應用資訊查詢請求串,下面“appid”需替換為待查詢的應用ID,需包含Authorization授權簽名參數(無需指定查詢參數)
/v3/openapi/apps/appid
推送資料path(tab 是要推送到應用中的某個具體表名,也需替換為自己應用表名)
/v3/openapi/apps/app_schema_demo/tab/actions/bulk
構建 query 部分
query 部分由查詢參數構成,參數為索引值對形式
為需要指定的查詢參數設定對應的參數值,並去掉value為空白的參數(value為空白的參數不計算簽名)
再對每一個參數按照先比較
參數名
後比較參數值
的順序,按照字典升序再對每一部分的
參數名
和參數值
進行 urlencode(指定RFC 3986模式),再將參數名和對應參數值之間通過=
拼接再將各個查詢參數之間用
&
分割拼接並儲存到 query 字串中最後按照 path + ? + query 方式拼接至CanonicalizedResource字串中,即完成查詢操作CanonicalizedResource參數構建,樣本如下:
/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson
以上請求串中主要包含的參數及參數值描述如下:
fetch_fields=name
以上請求串中主要包含的query參數中各子句及參數值描述如下(第一個是query參數,第二個是query子句及其它相關子句):
query=query=name:'文檔'&&sort=id&&config=format:fulljson
在urlencode之前,query參數中各個查詢子句之間必須要用 && 進行拼接,若為推送操作,則只需將 path 部分拼接至 CanonicalizedResource 字串中即可
構建 Authorization 欄位
構建方法參考開頭部分描述,需添加到請求 Header 中。假如AccessKeyId 為LTAItQcybixt
****,Signature為 1P7tfEh+CU5kFYRXzZ14kkJU
****,則python3範例程式碼大致如下:
headers['Authorization'] = 'OPENSEARCH ' + 'LTAIt****xt****' + ':' + '1P7tf*******4kkJU****'
簽名樣本
假如參數值如下
Authorization值為
OPENSEARCH LTAItQ****R9A0:1P7tfEh+CU******14kkJ
****AccessKeySecret值為
R0OGKs*******khMqHXBfKG
請求方式為
GET
Content-MD5值為空白,此處作為查詢請求
Content-Type值為
application/json
Date值為
2019-02-25T10:09:57Z
CanonicalizedOpenSearchHeaders值為
x-opensearch-nonce:15510****1704
CanonicalizedResource值為
/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson
請求Header | 簽名字串計算公式 | 樣本 |
‘Content-MD5’: ‘’, ‘Content-Type’: ‘application/json’, ‘Authorization’: ‘OPENSEARCH LTA****tR9A0:1P7tfEh+CU****RXzZ14kkJUAMc=’,‘X-Opensearch-Nonce’: ‘1551089397451704’,‘Date’: ‘2019-02-25T10:09:57Z’ | Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n”+ Content-Md5 + “\n”+ Content-Type + “\n”+ Date + “\n”+ CanonicalizedOpenSearchHeaders+ CanonicalizedResource)) | R0OGKs*******khMqHXBfKG,GET\n\napplication/json\n2019-02-25T10:09:57Z\nx-opensearch-nonce:1551089397451704\n/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson |
請求Header中參數值需與簽名方法中對應參數值保持一致
可用以下方法計算簽名(Signature)
以 hash_hmac 和 base64_encode 編碼產生加密值作為Signature
python3 範例程式碼:
import hmac
import base64
signature_string = '\n'.join(['GET',
'',
'application/json',
'2019-02-25T10:09:57Z',
'x-opensearch-nonce:1551089397451704',
'/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson'])
signature_hmac = hmac.new('R0OGKsMj******khMqHXBfKG'.encode('utf-8'), signature_string.encode('utf-8'), 'sha1')
signature = base64.b64encode(signature_hmac.digest())
假如AccessKeySecret值為 R0OGKsMj0*********HXBfKG
那麼通過上面的簽名方法構造出來的簽名值為 1P7tfEh+CU5*******kkJUAMc=
構建請求串
請求串 = host + CanonicalizedResource
需在 HTTP 要求 Header 頭資訊中增加 Authorization(授權)來包含簽名(Signature)資訊,表明該請求已被授權,同時Header中也需要包含上面提到的這些相關的請求Header。(host為應用訪問API地址)
最終search查詢請求串
http://host/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson
最終suggest查詢請求串
http://host/v3/openapi/apps/{appName}/suggest/{suggestName}/search?hits=10&query=%E6%A0%87%E9%A2%98
最終查詢指定應用資訊查詢請求串,下面最後一部分為“appid”值,假設為120001234該值,替換後如下所示,該查詢請求也需包含Authorization授權簽名參數(無需指定查詢參數)
http://host/v3/openapi/apps/120001234
最終推送資料請求串,此處推送資料需放在body體中
http://host/v3/openapi/apps/app_schema_demo/tab/actions/bulk
目前已對外公開 v3版官方Java SDK、PHP SDK、Python SDK,C# SDK,且PHP SDK和Python SDK、C# SDK已包含v3API簽名過程實現源碼,直接調用這些方法即可使用,也可參考 PHP SDK和Python SDK、C# SDK簽名實現過程源碼來實現其它語言SDK。
後續使用者參考該文檔以及源碼實現的 SDK 由使用者自己維護。
應用結構模板
{
"name": "app_schema_demo",
"type": "standard",
"schema": {
"indexes": {
"search_fields": {
"id": {
"fields": [
"id"
]
},
"name": {
"fields": [
"name"
],
"analyzer": "chn_standard"
},
"phone": {
"fields": [
"phone"
],
"analyzer": "fuzzy"
},
"int_arr": {
"fields": [
"int_arr"
]
},
"literal_arr": {
"fields": [
"literal_arr"
]
},
"cate_id": {
"fields": [
"cate_id"
]
}
},
"filter_fields": [
"id",
"int_arr",
"literal_arr",
"float_arr",
"cate_id"
]
},
"tables": {
"tab": {
"name": "tab",
"fields": {
"id": {
"name": "id",
"type": "INT",
"primary_key": true
},
"name": {
"name": "name",
"type": "TEXT",
"primary_key": false
},
"phone": {
"name": "phone",
"type": "SHORT_TEXT",
"primary_key": false
},
"int_arr": {
"name": "int_arr",
"type": "INT_ARRAY",
"primary_key": false
},
"literal_arr": {
"name": "literal_arr",
"type": "LITERAL_ARRAY",
"primary_key": false
},
"float_arr": {
"name": "float_arr",
"type": "FLOAT_ARRAY",
"primary_key": false
},
"cate_id": {
"name": "cate_id",
"type": "INT",
"primary_key": false
}
},
"primary_table": true
}
},
"route_field": null
},
"data_sources": [],
"first_ranks": {},
"second_ranks": {},
"summary": [],
"fetch_fields": [
"id",
"name",
"phone",
"int_arr",
"literal_arr",
"float_arr",
"cate_id"
],
"quota": {
"qps": 6,
"doc_size": 0.3
}
}