網上沒有找到C#版 的簽名代碼,只好去一字一字的讀SDK文檔,自己寫了一個,沒有在CSDN搞什么積分下載,寫的不好勿噴,能用點個贊再走.
空參和空的請求頭是通過了與官方網的驗證了,沒有問題,可以直接下載COS中的文件.如果要帶參,帶頭就自己試一下,如有有錯告訴我一下再走.
文件名沒有做過中文名的,我沒有打算存中文的文件名,所以沒有字符串特殊處理,用最簡單的方式達到目的.
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Web; /// <summary> /// CosSignature 的摘要說明 生成騰訊雲COS簽名類 /// ======作者:rovedog /// ======日期:2020.2.24 /// </summary> public class CosSignature { /// <summary> /// 密碼ID /// </summary> public string SecretId { get; set; } /// <summary> /// 密碼內容 /// </summary> public string SecretKey { get; set; } /// <summary> /// 開始時間 /// </summary> public DateTime StartTimestamp { get; set; } = DateTime.Now; /// <summary> /// 簽名有效期,單位秒,默認10分鍾 /// </summary> public int ExpiredTime { get; set; } = 600; /// <summary> /// 請求參數 /// </summary> public NameValueCollection NVC; /// <summary> /// 請求頭 /// </summary> public WebHeaderCollection RequestHeader; /// <summary> /// 請求方法 /// </summary> public string HttpMethod { get; set; } = "get"; /// <summary> /// 請求的url /// 若需驗證url參數則填寫,key小寫,value需要進行URLEncode,多個key以字典排序,如:max-keys=20&prefix=abc /// </summary> ///<example>簽名中的請求路徑以 / 開頭,無需URLEncode,如:/ 、 /a/b 或 /測試.jpg</example> public string HttpURI { get; set; } /// <summary> /// 實例初始化對象 /// </summary> /// <param name="secretId"></param> /// <param name="secretKey"></param> /// <param name="HttpUri"></param> public CosSignature(string secretId, string secretKey, string HttpUri = "/") { HttpURI = HttpUri; SecretId = secretId; SecretKey = secretKey; } /// <summary> /// 創建一個簽名 /// </summary> /// <returns></returns> public Return Create() { Return R = new Return(); HttpMethod = HttpMethod.ToLower(); List<string> M = new List<string> {"get", "post", "put", "delete", "head"}; if (M.IndexOf(HttpMethod) == -1) { R.BOOL = false; R.Error = "未知請求方法!"; return R; } if (string.IsNullOrEmpty(SecretId)) { R.BOOL = false; R.Error = "密碼ID為空!"; return R; } if (string.IsNullOrEmpty(SecretKey)) { R.BOOL = false; R.Error = "密碼內容為空!"; return R; } if (StartTimestamp > DateTime.Now) StartTimestamp = DateTime.Now; //步驟1:生成 KeyTime long startTimestamp = (StartTimestamp.ToUniversalTime().Ticks - 621355968000000000) / 10000000; long endTimestamp = startTimestamp + ExpiredTime; string keyTime = string.Format("{0};{1}", startTimestamp, endTimestamp); //步驟2:生成 SignKey string SignKey = HMACSHA1(SecretKey, keyTime); //步驟3:生成 UrlParamList 和 HttpParameters List<string> Key = new List<string>(); List<string> KeyValue = new List<string>(); Dictionary<string, string> Param = new Dictionary<string, string>(); if (NVC != null) { foreach (var k in NVC.Keys) { string kk = HttpUtility.UrlEncode(k.ToString()).ToLower(); Param.Add(kk, HttpUtility.UrlEncode(NVC[k.ToString()])); Key.Add(kk); } Key.Sort(); foreach (var k in Key) { KeyValue.Add(string.Format("{0}={1}", k, Param[k])); } } string HttpParameters = NVC != null ? string.Join("&", KeyValue.ToArray()) : ""; string UrlParamList = NVC != null ? string.Join(";", Key) : ""; //步驟4:生成 HeaderList 和 HttpHeaders Key.Clear(); Dictionary<string, string> Hearder = new Dictionary<string, string>(); if (RequestHeader != null) { foreach (var k in RequestHeader.AllKeys) { string kk = HttpUtility.UrlEncode(k).ToLower(); Hearder.Add(kk, HttpUtility.UrlEncode(RequestHeader[k])); Key.Add(kk); } Key.Sort(); KeyValue.Clear(); foreach (var k in Key) { KeyValue.Add(string.Format("{0}={1}", k, Hearder[k])); } } string HttpHeaders = RequestHeader != null ? string.Join("&", KeyValue.ToArray()) : ""; string HeaderList = RequestHeader != null ? string.Join(";", Key) : ""; //步驟5:生成 HttpString string HttpString = string.Format("{0}\n{1}\n{2}\n{3}\n", HttpMethod, HttpURI, HttpParameters, HttpHeaders); //步驟6:生成 StringToSign string StringToSign = string.Format("sha1\n{0}\n{1}\n", keyTime, SHA1(HttpString)); //步驟7:生成 Signature string Signature = HMACSHA1(SignKey, StringToSign); //步驟8:生成簽名 R.STRING = string.Format("q-sign-algorithm=sha1&q-ak={0}&q-sign-time={1}&q-key-time={1}&q-header-list={2}&q-url-param-list={3}&q-signature={4}", SecretId, keyTime, HeaderList, UrlParamList, Signature); //List<string> o = new List<string> {string.Format("SignKey={0}", SignKey), string.Format("HttpString={0}", HttpString), string.Format("StringToSign={0}", StringToSign)}; //R.OBJECT = string.Join("<br/>", o); return R; } /// <summary> /// HMACSHA1加密方法 /// </summary> /// <param name="content"></param> /// <param name="secretKey"></param> /// <returns></returns> public static string HMACSHA1(string secretKey, string content) { byte[] keyByte = Encoding.Default.GetBytes(secretKey); HMACSHA1 hmacsha1 = new HMACSHA1(keyByte); byte[] messageBytes = Encoding.Default.GetBytes(content); byte[] hashmessage = hmacsha1.ComputeHash(messageBytes); StringBuilder sb = new StringBuilder(""); foreach (byte b in hashmessage) { sb.AppendFormat("{0:x2}", b); } return sb.ToString(); } /// <summary> /// SHA1加密方法 /// </summary> /// <param name="content"></param> /// <returns></returns> public static string SHA1(string content) { var sha1 = new SHA1CryptoServiceProvider(); byte[] c = Encoding.Default.GetBytes(content); byte[] sc = sha1.ComputeHash(c); StringBuilder sb = new StringBuilder(""); foreach (byte b in sc) { sb.AppendFormat("{0:x2}", b); } return sb.ToString(); } }
其中Return是自創了一個神奇的返回類型,想怎么返回就怎么返回,適用於不太講究性能和並發的應用,希望大佬指點迷津,不用的話改成自己的字符返回類型,
/// <summary> /// 需要多個返值的值類型 2019.4.10 /// </summary> [Serializable] public class Return { public Return() { BOOL = true; INT = 0; STRING = ""; Error = ""; Information = ""; ExcuteTime = 0; } /// <summary> /// 布爾型返回結果,默認是true /// </summary> public bool BOOL { get; set; } /// <summary> /// 整型返回結果 /// </summary> public int INT { get; set; } /// <summary> /// 字符串類型結果返回 /// </summary> public string STRING { get; set; } /// <summary> /// 可序列化的object類型返回結果 /// </summary> public object OBJECT { get; set; } /// <summary> /// 執行的相關信息 /// </summary> public string Information { get; set; } /// <summary> /// 錯誤消息 /// </summary> public string Error { get; set; } /// <summary> /// 執行時間 /// </summary> public long ExcuteTime { get; set; } }
補記:后台與官方客服聯系,有提供 :https://cloud.tencent.com/document/product/436/32873