"根据[链接]的描述,踩了若干个坑,把源码贴出来,做个分享。 包含签名过程的代码: private static IResponsePack RequestAliyun(string apiPath, dynamic data, string method = 'GET') { var dic = new RouteVa .."

阿里云开放搜索(Open Search)C# 版签名代码 ·Signature 生成算法

本贴最后更新于 695 天前,其中的信息可能已经事过境迁

根据官方文档的描述,踩了若干个坑,把源码贴出来,做个分享。

包含签名过程的代码:

private static IResponsePack RequestAliyun(string apiPath, dynamic data, string method = "GET")
{
    var dic = new RouteValueDictionary(data);
    dic["Version"] = "v2";
    dic["AccessKeyId"] = AccessKeyId;

    dic["SignatureMethod"] = "HMAC-SHA1";
    dic["Timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH🇲🇲ssZ");

    dic["SignatureVersion"] = "1.0";
    dic["SignatureNonce"] = Guid.NewGuid().ToString();

    // 开始生成 Signature
    string[] array = dic.OrderBy(a => a.Key, StringComparer.Ordinal).Select(a => PercentEncode(a.Key) + "=" + PercentEncode(a.Value.ToString())).ToArray();
    string dataStr = string.Join("&", array);
    string signStr = method + "&" + PercentEncode("/") + "&" + PercentEncode(dataStr);

    HMACSHA1 myhmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(AccessKeySecret + "&"));
    byte[] byteArray = Encoding.UTF8.GetBytes(signStr);
    MemoryStream stream = new MemoryStream(byteArray);
    string signature = Convert.ToBase64String(myhmacsha1.ComputeHash(stream));

    dic["Signature"] = signature;

    // 这里的 WebBrowser 对象是我自己封装的一个 WebClient 类。
    // 在 NuGet 中可以下载到:https://www.nuget.org/packages/Zane.Common.WebBrowser
    // 源码:https://github.com/LyZane/Zane.Common/tree/master/Zane.Common.WebBrowser
    WebBrowser browser = new WebBrowser(new RequestConfig() { Method = method });
    return browser.DownloadJson(new Uri(APIHost, apiPath), dic);
}

private static string PercentEncode(string value)
{
    return UpperCaseUrlEncode(value)
        .Replace("+", "%20")
        .Replace("*", "%2A")
        .Replace("%7E", "~");
}

private static string UpperCaseUrlEncode(string s)
{
    char[] temp = HttpUtility.UrlEncode(s).ToCharArray();
    for (int i = 0; i < temp.Length - 2; i++)
    {
        if (temp[i] == '%')
        {
            temp[i + 1] = char.ToUpper(temp[i + 1]);
            temp[i + 2] = char.ToUpper(temp[i + 2]);
        }
    }
    return new string(temp);
}

调用,以使用索引进行搜索为例:

var response = RequestAliyun("search", new
{
    query = BuildQueryString(where),
    index_name = IndexName
});

在此过程中遇到的最大坑就是:使用 C# 的 HttpUtility.UrlEncode() 编码得到的形如 %xx%xx%xx%xx 的内容是小写的,Java 的是大写的。 后来也是在博客园查到一篇帖子提示到了这点,然后才成功。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:PipeSoloSymWide 等,欢迎大家加入,贡献开源。

    2618 引用 • 4216 回帖 • 633 关注
  • 阿里云
    62 引用 • 336 回帖
  • C#
    17 引用 • 16 回帖 • 1 关注
感谢    关注    收藏    赞同    反对    举报    分享
2 回帖    
请输入回帖内容...
  • Zane API      

    谢谢博主

    感谢    赞同    反对    举报    分享       回复
  • someone API      

    如果能提供 所有的源代码就更好了!!!

    感谢    赞同    反对    举报    分享       回复