閱讀124 返回首頁    go 人物


請求簽名__API-Reference_日誌服務-阿裏雲

為保證用戶日誌數據的安全,Log Service API的所有HTTP請求都必須經過安全驗證。目前,該安全驗證基於阿裏雲的訪問秘鑰,使用對稱加密算法完成的。其工作流程如下:

  1. 請求端根據API請求內容(包括HTTP Header和Body)生成簽名字符串
  2. 請求端使用阿裏雲的訪問秘鑰對(AccessKeyID和AccessKeySecret)對第一步生成的簽名字符串進行簽名,形成該API請求的數字簽名
  3. 請求端把API請求內容和數字簽名一同發送給服務端
  4. 服務端在接到請求後會重複如上的第一、二步工作(注:服務端會在後台取得該請求使用的用戶訪問秘鑰對)並在服務端計算出的該請求期望的數字簽名
  5. 服務端用期望的數字簽名和請求端發送過來的數字簽名做比對,如果完全一致則認為該請求通過安全驗證。否則直接拒絕該請求。

上麵整個流程也可以使用下圖直觀描述:

通過上麵的安全驗證流程,可以幫助我們達到如下目的:

  • 確認哪位用戶在做API請求。因為在發送請求前需要用戶指定生成數字簽名的秘鑰對,在服務端即可通過該秘鑰對確定用戶身份,進而可做訪問權限管理。
  • 確認用戶請求在網絡傳輸過程中有無被篡改。因為服務端會對接收到的請求內容重新計算數字簽名,一旦請求內容在網絡上被篡改,則無法通過數字簽名比對。

簽名API請求

為通過API請求的安全驗證,用戶需要在客戶端對其API請求進行簽名(即生成正確的數字簽名),並且使用HTTP頭“Authorization”在網絡上傳輸該請求的數字簽名。Authorization頭的具體格式如下:

Authorization:LOG <AccessKeyId>:<Signature>

如上格式所示,Authorization頭的值包含用戶訪問秘鑰對中的AccessKeyId,且與之對應的AccessKeySecret將用於Signature值的構造。下麵將詳細解釋如何構造該Signature值。

第一步:準備合適的阿裏雲訪問秘鑰

如上所述,給API請求生成簽名,需使用一對訪問秘鑰(AccessKeyId/AccessKeySecret)。用戶可以使用已經存在的訪問秘鑰對,也可以創建新的訪問秘鑰對。但需要保證使用的秘鑰對處在“啟用”狀態。

第二步:生成請求的簽名字符串

LOG API的簽名字符串由HTTP請求中的Method,Header和Body信息一同生成,具體方式如下:

SignString = VERB + "n"
             + CONTENT-MD5 + "n"
             + CONTENT-TYPE + "n"
             + DATE + "n"
             + CanonicalizedLOGHeaders + "n"
             + CanonicalizedResource

上麵公式中的“n"表示換行轉義字符,+(加號)表示字符串連接操作,其他各個部分定義如下:

名稱 定義 示例
VERB HTTP請求的方法名稱 PUT,GET,POST等
CONTENT-MD5 HTTP請求中Body部分的MD5值(必須為大寫字母串) 875264590688CA6171F6228AF5BBB3D2
CONTENT-TYPE HTTP請求中Body部分的類型 application/x-protobuf
DATE HTTP請求中的標準時間戳頭(遵循RFC 1123格式,使用GMT標準時間) Mon, 3 Jan 2010 08:33:47 GMT
CanonicalizedLOGHeaders 由HTTP請求中以x-log和x-acs為前綴的自定義頭構造的字符串(具體構造方法見下麵詳述) x-log-apiversion:0.6.0nx-log-bodyrawsize:50nx-log-signaturemethod:hmac-sha1
CanonicalizedResource 由HTTP請求資源構造的字符串(具體構造方法見下麵詳述) /logstores/app_log

對於部分無Body的HTTP請求,其CONTENT-MD5和CONTENT-TYPE兩個域為空字符串,這時整個簽名字符串的生成方式如下:

SignString = VERB + "n"
             + "n"
             + "n"
             + DATE + "n"
             + CanonicalizedLOGHeaders + "n"
             + CanonicalizedResource

正如公共請求頭中描述,LOG API中引入了一個自定義請求頭x-log-date。如果用戶請求中指定了該請求頭,則其值會替代HTTP標準請求頭Date加入簽名計算。

“CanonicalizedLOGHeaders”的構造方式如下:

1. 將所有以x-log和x-acs為前綴的HTTP請求頭的名字轉換成小寫字母;
2. 將上一步得到的所有LOG自定義請求頭按照字典序進行升序排序;
3. 刪除請求頭和內容之間分隔符兩端出現的任何空格;
4. 將所有的頭和內容用n分隔符組合成最後的CanonicalizedLOGHeader;

CanonicalizedResource的構造方式如下:

1. 將CanonicalizedResource設置為空字符串("");
2. 放入要訪問的LOG資源,如"/logstores/logstorename"(無logstorename則不填);
3. 如請求包含查詢字符串(QUERY_STRING),則在CanonicalizedResource字符串尾部添加“?”和查詢字符串。

其中QUERY_STRING是URL中請求參數按字典序排序後的字符串,其中參數名和值之間用“=”(等號)相隔組成字符串,並對參數名-值對按照字典序升序排序,然後以’&’符號連接構成字符串。其公式化描述如下:

QUERY_STRING = "KEY1=VALUE1" + "&" + "KEY2=VALUE2"
第三步:生成請求的數字簽名

目前,LOG API隻支持一種數字簽名算法,即默認簽名算法"hmac-sha1"。其整個簽名公式如下:

Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))

簽名的方法用RFC 2104中定義的HMAC-SHA1方法 如上公式用的AccessKeySecret必須和最終的Authorization頭中使用的AccessKeyId相對應。否則,請求將無法通過服務端驗證。

在計算出數字簽名後,使用該值按本節最前麵描述的Authorization頭格式構建完整的LOG API請求安全驗證頭,並填入HTTP請求中即可發送。

請求簽名過程示例

為更好地理解整個請求簽名的流程,我們用兩個示例來演示整個過程。首先,假設用戶用做LOG API簽名的訪問秘鑰對如下:

AccessKeyId = "bq2sjzesjmo86kq35behupbq"
AccessKeySecret = "4fdO2fTDDnZPU/L7CHNdemB2Nsk="
示例一:

用戶需要發送如下GET請求列出“ali-test-project”項目下的所有LogStores,其HTTP請求如下:

GET /logstores HTTP 1.1
Mon, 09 Nov 2015 06:11:16 GMT
Host: ali-test-project.cn-hangzhou-devcommon-intranet.sls.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1

如上LOG API請求生成的簽名字符串為:

GETnnnMon, 09 Nov 2015 06:11:16 GMTnx-log-apiversion:0.6.0nx-log-signaturemethod:hmac-sha1n/logstores?logstoreName=&offset=0&size=1000

由於是GET請求,該請求無任何HTTP Body,所以生成的簽名字符串中CONTENT-TYPE與CONTENT-MD5域為空字符串。如果以前麵指定的用戶AccessKeySecret做簽名運算後得到的簽名為:

jEYOTCJs2e88o+y5F4/S5IsnBJQ=

最後發送經數字簽名的HTTP請求內容如下:

GET /logstores HTTP 1.1
Mon, 09 Nov 2015 06:11:16 GMT
Host: ali-test-project.cn-hangzhou-devcommon-intranet.sls.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1
Authorization: LOG bq2sjzesjmo86kq35behupbq:jEYOTCJs2e88o+y5F4/S5IsnBJQ=
示例二:

用戶需要給同上例"ali-test-project"項目中名為"test-logstore"的Logstore寫入下麵日誌:

topic=""
time=1447048976
source="10.230.201.117"
"TestKey": "TestContent"

為此,按照LOG API定義需要構建如下HTTP請求:

POST /logstores/test-logstore HTTP/1.1
Date: Mon, 09 Nov 2015 06:03:03 GMT
Host: test-project.cn-hangzhou-devcommon-intranet.sls.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1
Content-MD5: 1DD45FA4A70A9300CC9FE7305AF2C494
Content-Length: 52
x-log-apiversion:0.6.0
x-log-bodyrawsize:50
x-log-compresstype:lz4
x-log-signaturemethod:hmac-sha1

<日誌內容序列化成ProtoBuffer格式的字節流>

在這個HTTP請求中,寫入的日誌內容首先被序列化成ProtoBuffer格式(請參考ProtoBuffer格式了解該格式的更多細節)後作為請求Body。所以該請求的Content-Type頭的值指定為application/x-protobuf。類似,Content-MD5頭的值是請求body對應的MD5值。按照上麵的簽名字符串構造方式,這個請求對應的簽名字符串為:

POSTn1DD45FA4A70A9300CC9FE7305AF2C494napplication/x-protobufnMon, 09 Nov 2015 06:03:03 GMTnx-log-apiversion:0.6.0nx-log-bodyrawsize:50nx-log-compresstype:lz4nx-log-signaturemethod:hmac-sha1n/logstores/test-logstore

同樣,以前麵示例中的用戶AccessKeySecret做簽名運算,得到的最終簽名為:

XWLGYHGg2F2hcfxWxMLiNkGki6g=

最後發送經數字簽名的HTTP請求內容如下:

POST /logstores/test-logstore HTTP/1.1
Date: Mon, 09 Nov 2015 06:03:03 GMT
Host: test-project.cn-hangzhou-devcommon-intranet.sls.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1
Content-MD5: 1DD45FA4A70A9300CC9FE7305AF2C494
Content-Length: 52
x-log-apiversion:0.6.0
x-log-bodyrawsize:50
x-log-compresstype:lz4
x-log-signaturemethod:hmac-sha1
Authorization: LOG bq2sjzesjmo86kq35behupbq:XWLGYHGg2F2hcfxWxMLiNkGki6g=

<日誌內容序列化成ProtoBuffer格式的字節流>

最後更新:2016-05-06 10:44:22

  上一篇:go 公共響應頭__API-Reference_日誌服務-阿裏雲
  下一篇:go 通用錯誤碼__API-Reference_日誌服務-阿裏雲