C# 阿里云接口签名算法

C# 1997次浏览 本站
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace RC.Domain
{
    /// <summary>
    ///     Aliyun接口签名算法,以调用域名接口为例,调用方式见下面代码
    ///     注意事项:
    ///     1.AccessKeyId和AccessKeySecret,在阿里云控制台查看。
    ///     2.注意接口Version和接口地址,不同接口的版本和请求地址是不一样的。
    ///     参考:https://help.aliyun.com/document_detail/42884.html?spm=a2c4g.11186623.6.767.7ea976dbSQ3DnF
    /// </summary>
    public class AliyunHelper
    {
        //【调用方式】
        //var parameters = new Dictionary<string, string>
        //{
        //    {"Action", "DescribeDomainRecords"},
        //    {"DomainName", "qingshanboke.com"}
        //};
        //var helper = new AliyunHelper("alidns.aliyuncs.com", parameters)
        //{
        //    AccessKeyId = txtAppKey.Text,
        //    AccessKeySecret = txtSecret.Text,
        //    Version = "2015-01-09"
        //};
        //var result = helper.DoRequest();
        //txtLog.Text = result;

        private readonly Dictionary<string, string> _parameters;

        /// <summary>
        ///     阿里云颁发给用户的访问服务所用的密钥ID
        /// </summary>
        public string AccessKeyId = "****************";

        /// <summary>
        ///     阿里云颁发给用户的访问服务所用的密钥
        /// </summary>
        public string AccessKeySecret = "******************";

        public string ApiUrl;

        /// <summary>
        ///     返回值的类型,支持JSON与XML。默认为XML
        /// </summary>
        public string Format = "JSON";

        /// <summary>
        ///     API版本号,为日期形式:YYYY-MM-DD,本版本对应为2016-05-11
        /// </summary>
        public string Version = "2016-05-11";

        public AliyunHelper(string apiUrl, Dictionary<string, string> parameters)
        {
            ApiUrl = apiUrl;
            _parameters = parameters;
        }


        /// <summary>
        ///     签名结果串
        /// </summary>
        public string Signature { get; set; }


        private void BuildParameters()
        {
            _parameters.Add("Format", Format.ToUpper());
            _parameters.Add("Version", Version);
            _parameters.Add("AccessKeyId", AccessKeyId);
            _parameters.Add("SignatureVersion", "1.0");
            _parameters.Add("SignatureMethod", "HMAC-SHA1");
            _parameters.Add("SignatureNonce", Guid.NewGuid().ToString());
            _parameters.Add("Timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"));
        }

        public void ComputeSignature()
        {
            BuildParameters();

            var canonicalizedQueryString = string.Join("&",
                _parameters.OrderBy(x => x.Key).Select(x => PercentEncode(x.Key) + "=" + PercentEncode(x.Value)));

            var stringToSign = "GET&" + PercentEncode("/") + "&" + PercentEncode(canonicalizedQueryString);
            var keyBytes = Encoding.UTF8.GetBytes(AccessKeySecret + "&");
            var hmac = new HMACSHA1(keyBytes);
            var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            Signature = Convert.ToBase64String(hashBytes);
            _parameters.Add("Signature", Signature);
        }

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

        private static string UpperCaseUrlEncode(string s)
        {
            var temp = HttpUtility.UrlEncode(s).ToCharArray();
            for (var 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);
        }

        public string DoRequest()
        {
            ComputeSignature();
            var host = ApiUrl.ToLower().StartsWith("http") ? ApiUrl : "http://" + ApiUrl;
            host = host.TrimEnd('/');
            var url = host + "/?" +
                      string.Join("&", _parameters.OrderBy(x => x.Key).Select(x => x.Key + "=" + HttpUtility.UrlEncode(x.Value)));
            return HttpGet(url);
        }

        public static string HttpGet(string url)
        {
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(url);
                using (var response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        var stream = response.GetResponseStream();
                        string s = null;
                        if (stream != null)
                        {
                            using (var reader = new StreamReader(stream, Encoding.UTF8))
                            {
                                s = reader.ReadToEnd();
                                reader.Close();
                            }

                            stream.Close();
                        }

                        return s;
                    }
                    return "请求 " + url + " 报错:" + response.StatusCode;
                }
            }
            catch (WebException ex)
            {
                var response = (HttpWebResponse)ex.Response;
                if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    using (Stream data = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(data))
                        {
                            string text = reader.ReadToEnd();
                            return text;
                        }
                    }
                }
                return "请求 " + url + " 报错:" + response.StatusCode + " " + ex.Message;
            }
        }
    }
}
            

发表评论

电子邮件地址不会被公开。 必填项已用*标注