1. 程式人生 > >踩坑記:C#訪問阿里雲的API小結,阿里雲的文件有待改善……

踩坑記:C#訪問阿里雲的API小結,阿里雲的文件有待改善……

為運維管理方便需要,寫了一個小工具去呼叫阿里雲的API,包括操作ECS、SLB、域名等等API,結果就這麼一點點小東西,也被阿里雲的文件坑了好多次,下面5個問題,有3個跟阿里雲文件相關……
關鍵是阿里雲的客服服務還差……

1、計算簽名的AccessKeySecret不能直接用,要在末尾新增一個 &

比如AccessKeySecret是“testsecret”,那麼用於計算 HMAC 的 Key 為 “testsecret&”
這個很讓我無語,為啥要加這個玩意?AccessKeySecret已經是30個字元的隨機串了,想當然的直接拿去計算,文件裡雖然寫了,但是稍不留神就會遺漏……

2、阿里雲的文件上給出的簽名值是錯誤的,這個沒人校驗嗎?

參考文件:https://help.aliyun.com/document_detail/42884.html
這裡寫圖片描述
這裡文件上給出的源串是:
GET&%2F&AccessKeyId%3Dtestid%26Action%3DCheckDomain%26Format%3DJSON%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D5033a7d9-dfeb-417d-9fdf-13459fe90c1a%26SignatureVersion%3D1.0%26TimeStamp%3D2016-05-19T09%253A06%253A05Z%26Version%3D2016-05-11
算出的簽名應該是:rdQZIariLRvk14Mmfc5YvAA6GwQ=
但是文件上說是:WXkgFH4ymmnCjSUM65f6I1n7%2FUs=
被坑的半死,還好沒再去驗證這個源串,直接呼叫API,是成功的……
而且,阿里雲網頁上的智慧顧問,回答這個簽名問題時,給出的簽名結果也是錯誤的,並且,簽名的相關描述,可以搜尋出很多個結果,每個結果都有差異,有的居然沒有UrlEncode……
還好實際的API呼叫是統一的,沒有區別,阿里雲內部文件真夠混亂的:
這裡寫圖片描述

3、不同區域的api域名還不一樣,最坑的是阿里雲找不到任何這方面的資料

比如獲取slb資訊的介面,API概覽和API具體描述裡的Demo,都明確寫著:
Endpoint:負載均衡API的服務接入地址為slb.aliyuncs.com
https://help.aliyun.com/document_detail/27568.html
https://help.aliyun.com/document_detail/27582.html
實際上,用這個地址獲取華南的slb能正常,獲取其它地方,比如華北3(張家口)或德國的slb,永遠是獲取不到的……
後來懷疑是我的呼叫方式不對,就下載阿里雲的SDK測試了一下,居然能獲取到,
抓包看了一下,發現阿里雲的SDK是發起了2次http請求,先查Endpoint,再查具體的api:
就是這個介面查Endpoint:

http://location.aliyuncs.com/?Version=2015-06-12&Action=DescribeEndpoints
好吧,我用關鍵字:DescribeEndpoints 去阿里查一查,居然沒有結果:
這裡寫圖片描述
另外,阿里雲的SDK也有bug,會快取,我如果先讀取華南的SLB,再獲取華北的SLB,它就讀取不到資料了……

4、HMAC計算出的簽名含有+=/等特殊字元,提交前要UrlEncode

這個是我的錯,之前做的介面簽名都是MD5簽名,不存在特殊字元,直接拼接就ok了,阿里雲使用的是HMAC簽名,結果可能出現特殊字元,導致我在呼叫時,有時正常,有時出錯,被這問題糾結了半天,才通過抓包發現

5、C#的UrlEncode,特殊字元是小寫,阿里雲要求大寫

比如等號=, C#的UrlEncode得出的結果是 %3d,但是阿里雲要求用 %3D,這個只能自己重寫一下UrlEncode了,參考程式碼如下:

/// <summary>
/// 阿里雲要求的UrlEncode是大寫的……
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static String PercentEncode(String value)
{
    if (string.IsNullOrEmpty(value))
        return "";
    var lowStr = HttpUtility.UrlEncode(value, Encoding.UTF8);

    // HttpUtility.UrlEncode編碼值為小寫,要轉換為大寫
    var sb = new StringBuilder(lowStr);
    int i = lowStr.IndexOf('%'), j = sb.Length;
    while (i >= 0 && i + 2 < j) // 找到%,且後面還有2個字元時進入迴圈
    {
        if (sb[i + 1] >= 'a')
            sb[i + 1] = (char)(sb[i + 1] - 32);
        if (sb[i + 2] >= 'a')
            sb[i + 2] = (char)(sb[i + 2] - 32);
        i = lowStr.IndexOf('%', i + 2);
    }
    sb.Replace("+", "%20").Replace("*", "%2A").Replace("%7E", "~");
    return sb.ToString();
}

暫時就這5個坑,後面再發現再補上