## **創建規范請求**
要開始簽名過程,請創建一個字符串,其中包含來自標準(規范)格式的請求的信息。這可確保 GSDATA 在收到請求時計算出的簽名與您計算出的簽名相同。
按照此處的步驟創建請求的規范版本。否則,您的版本與 GSDATA 計算得到的版本將不匹配,請求將被拒絕。
以下示例演示了創建規范請求的偽代碼。
**例 規范請求偽代碼**
~~~
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HexEncode(Hash(RequestPayload))
~~~
在此偽代碼中,Hash 表示生成消息摘要的函數,通常是 SHA-256。(在該過程中的稍后階段,您將指定要使用的哈希算法。)HexEncode 表示以小寫字母形式返回摘要的 base-16 編碼的函數。例如,HexEncode("m") 返回值 6d 而不是 6D。輸入的每一個字節都必須表示為兩個十六進制字符,java版本HexEncode。
以下示例演示如何構造規范形式的 API 請求。原始請求在從客戶端發送到 GSDATA 時可能看上去與此類似,不過此示例還不包括簽名信息。
~~~
GET http://api.gsdata.cn/weixin/v1/users?wx_name=rmrbwx&page=1&per-page=20 HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: api.gsdata.cn
x-gsdata-date: 20150830T123600Z
~~~
**要創建規范請求,請將以下來自每個步驟的部分連接為一個字符串:**
1. 首先是 HTTP 請求方法(GET、PUT、POST 等),后跟換行符。
**例 示例請求方法**
~~~
GET
~~~
2. 添加規范 URI 參數,后跟換行符。規范 URI 是 URI 的絕對路徑部分的 URI 編碼版本,該版本是 URI 中的一切 - 從 HTTP 主機到開始查詢字符串參數(如果有)的問號字符(“?”)。
根據 RFC 3986 標準化 URI 路徑。移除冗余和相對路徑部分。路徑中每個部分都必須為 URI 編碼。
3. 添加規范查詢字符串,后跟換行符。如果請求不包括查詢字符串,請使用空字符串(實際上是空白行)。示例請求具有以下查詢字符串。
**例 規范查詢字符串示例**
~~~
Action=ListUsers&Version=2010-05-08
~~~
要構建規范查詢字符串,請完成以下步驟:
1). 按字符代碼點以升序順序對參數名稱進行排序。例如,以大寫字母 F 開頭的參數名稱排在以小寫字母 b 開頭的參數名稱之前。
2). 根據以下規則對每個參數名稱和值進行 URI 編碼:
* 請勿對 RFC 3986 定義的任何非預留字符進行 URI 編碼,這些字符包括:A-Z、a-z、0-9、連字符 (-)、下劃線 (_)、句點 (.) 和波浪符 ( ~ )。
* 使用 %XY 對所有其他字符進行百分比編碼,其中“X”和“Y”為十六進制字符(0-9 和大寫字母 A-F)。例如,空格字符必須編碼為 %20(不像某些編碼方案那樣使用“+”),擴展 UTF-8 字符必須采用格式 %XY%ZA%BC。
3). 以排序后的列表中第一個參數名稱開頭,構造規范查詢字符串。
4). 對于每個參數,追加 URI 編碼的參數名稱,后跟等號字符 (=),再接 URI 編碼的參數值。對沒有值的參數使用空字符串。
5). 在每個參數值后追加與字符 (&),列表中最后一個值除外。
4. 添加規范標頭,后跟換行符。規范標頭包括您要包含在簽名請求中的所有 HTTP 標頭的列表。
您必須至少包含 host 標頭。標準標頭(如 content-type)是可選的。不同的服務可能需要其他標頭。
**例 規范標頭示例**
~~~
content-type:application/x-www-form-urlencoded; charset=utf-8\n
host:api.gsdata.cn\n
x-gsdata-date:20170620T123600Z\n
~~~
要創建規范標頭列表,請將所有標頭名稱轉換為小寫形式并刪除前導空格和尾隨空格。將標頭值中的連續空格轉換為單個空格。
以下偽代碼描述如何構造規范標頭列表:
~~~
CanonicalHeaders =
CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... + CanonicalHeadersEntryN
CanonicalHeadersEntry =
Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'
~~~
Lowercase 表示將所有字符轉換為小寫字母的函數。Trimall 函數刪除值前后的多余空格并將連續空格轉換為單個空格。
通過按字符代碼對(小寫)標頭排序,然后對標頭名稱進行迭代操作,來構建規范標頭列表。根據以下規則構造每個標頭:
追加小寫標頭名稱,后跟冒號。
追加該標頭的值的逗號分隔列表。請勿對有多個值的標頭進行值排序。
追加一個新行(“\n”)。
5. 添加已簽名的標頭,后跟換行符。該值是您包含在規范標頭中的標頭列表。通過添加此標頭列表,您可以向 GSDATA 告知請求中的哪些標頭是簽名過程的一部分以及在驗證請求時 GSDATA 可以忽略哪些標頭(例如,由代理添加的任何附加標頭)。
host 標頭必須作為已簽名標頭包括在內。如果包括日期或 x-gsdata-date 標頭,則還必須包括在已簽名標頭列表中的標頭。
要創建已簽名標頭列表,請將所有標頭名稱轉換為小寫形式,按字符代碼對其進行排序,并使用分號來分隔這些標頭名稱。以下偽代碼描述如何構建已簽名標頭的列表。Lowercase 表示將所有字符轉換為小寫字母的函數。
通過對按小寫字符代碼排序的標頭名稱集合進行迭代操作,構建已簽名標頭的列表。對于除最后一個標頭外的每個標頭名稱,請在標頭名稱后追加分號(“;”),將它與后面的標頭名稱分隔開。
6. 使用 SHA256 等哈希 (摘要) 函數以基于 HTTP 或 HTTPS 請求正文中的負載創建哈希值。簽名需要您使用UTF-8字符編碼來對負載中的文本進行編碼。
在創建待簽字符串后,請指定用于對負載進行哈希(SHA256)處理的簽名算法。指定 GSDATA-HMAC-SHA256 作為簽名算法。經過哈希處理的負載必須以小寫十六進制字符串形式表示。
如果負載為空,則使用空字符串作為哈希函數的輸入。
7. 要構建完整的規范請求,請將來自每個步驟的所有組成部分組合為單個字符串。如上所述,每個組成部分都以換行符結尾。如果您執行前述規范請求偽代碼,生成的規范請求將顯示在以下示例中。
8. 使用您對負載進行哈希處理時所使用的相同算法來創建規范請求的摘要(哈希)。