网上没有找到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} {1} {2} {3} ", HttpMethod, HttpURI, HttpParameters, HttpHeaders); //步骤6:生成 StringToSign string StringToSign = string.Format("sha1 {0} {1} ", 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