验证签名方法
[HttpGet] public HttpResponseMessage LockRegister(string 参数1, int 参数2, string 参数3, string 参数4, int 参数5 ……) { bool signResult = SignHelper.CheckSign(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().GetParameters(), this.ControllerContext.Request.RequestUri.Query);//验证签名方法 return null; }
返回参数签名
public class ResultMsg { public virtual string sign { get { return SignHelper.Sign(this); } } public int code { get; set; } public string msg { get; set; } } public class LockRegisterResult : ResultMsg { public string SerialNumber { get; set; } public List<DataTable> ListTab { get; set; } public new string sign { get { return SignHelper.Sign(this, new string[] { "ListTab" }); } } }
实现:
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> /// 通用方法类 /// </summary> public class SignHelper { private static string Key = ""; /// <summary> /// 签名 /// </summary> /// <typeparam name="T">泛型类</typeparam> /// <param name="t">传入this</param> /// <param name="ignorePropertys">忽略哪个属性不签名</param> /// <returns></returns> public static string Sign<T>(T t, string[] ignorePropertys = null) { Dictionary<string, string> dic = new Dictionary<string, string>(); var propertys = t.GetType().GetProperties(); foreach (var item in propertys) { if (item.Name.Equals("sign")) { continue;// 避免无限循环 } if (item.PropertyType.Namespace.ToLower().Equals("System.Collections.Generic".ToLower())) { continue; } bool ignore = false; if (ignorePropertys != null) { foreach (var ignoreProperty in ignorePropertys) { if (item.Name.Equals(ignoreProperty)) { ignore = true; break; } } } if (!ignore) { var value = item.GetValue(t, null); if (value != null && !string.IsNullOrEmpty(value.ToString())) { dic.Add(item.Name, value.ToString()); } } } return Sign(dic); } /// <summary> /// 签名 /// </summary> /// <param name="dicParams">签名参数</param> /// <returns></returns> public static string Sign(Dictionary<string, string> dicParams) { //将字典中按ASCII码升序排序 Dictionary<string, string> dicDestSign = new Dictionary<string, string>(); dicDestSign = AsciiDictionary(dicParams); var sb = new StringBuilder(); foreach (var sA in dicDestSign)//参数名ASCII码从小到大排序(字典序); { if (string.IsNullOrEmpty(sA.Value) || string.Compare(sA.Key, "sign", true) == 0) { continue;// 参数中为签名的项,不参加计算//参数的值为空不参与签名; } string value = sA.Value.ToString(); sb.Append(sA.Key).Append("=").Append(sA.Value).Append("&"); } var string1 = sb.ToString(); sb.Append(Key);//在stringA最后拼接上key=(API密钥的值)得到stringSignTemp字符串 var stringSignTemp = sb.ToString(); var sign = MD5(stringSignTemp, "UTF-8").ToUpper();//对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。 return sign; } /// <summary> /// MD5加密 /// </summary> /// <param name="encypStr">需要md5加密的字符串</param> /// <param name="charset">编码</param> /// <returns>返回加密后的MD5字符串</returns> public static string MD5(string encypStr, string charset = "UTF-8") { string retStr = string.Empty; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; //使用GB2312编码方式把字符串转化为字节数组. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } /// <summary> /// 将集合key以ascii码从小到大排序 /// </summary> /// <param name="sArray">源数组</param> /// <returns>目标数组</returns> public static Dictionary<string, string> AsciiDictionary(Dictionary<string, string> sArray) { Dictionary<string, string> asciiDic = new Dictionary<string, string>(); string[] arrKeys = sArray.Keys.ToArray(); Array.Sort(arrKeys, string.CompareOrdinal); foreach (var key in arrKeys) { string value = sArray[key]; asciiDic.Add(key, value); } return asciiDic; } #region 验证签名 /// <summary> /// 验证签名 /// </summary> /// <param name="parameters">当前方法参数数组</param> /// <param name="queryString">queryString</param> /// <returns></returns> public static bool CheckSign(System.Reflection.ParameterInfo[] parameters, string queryString) { System.IO.File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "\调用日志.csv", string.Format("{0},{1:yyyy-MM-dd HH:mm} ", queryString, DateTime.Now)); //return true; Dictionary<string, string> dic = new Dictionary<string, string>(); NameValueCollection col = GetQueryString(queryString); foreach (var property in parameters) { var value = col[property.Name]; //参数的值为空不参与签名;// 参数中为签名的项,不参加计算 if (property.Name.Equals("sign") || string.IsNullOrEmpty(value)) { continue; } dic.Add(property.Name, value); } string signResult = Sign(dic); return col["sign"].ToString().Equals(signResult); } /// <summary> /// 将查询字符串解析转换为名值集合. /// </summary> /// <param name="queryString">queryString</param> /// <returns></returns> private static NameValueCollection GetQueryString(string queryString) { return GetQueryString(queryString, null, true); } /// <summary> /// 将查询字符串解析转换为名值集合. /// </summary> /// <param name="queryString"></param> /// <param name="encoding"></param> /// <param name="isEncoded"></param> /// <returns></returns> private static NameValueCollection GetQueryString(string queryString, Encoding encoding, bool isEncoded) { queryString = queryString.Replace("?", ""); NameValueCollection result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); if (!string.IsNullOrEmpty(queryString)) { int count = queryString.Length; for (int i = 0; i < count; i++) { int startIndex = i; int index = -1; while (i < count) { char item = queryString[i]; if (item == '=') { if (index < 0) { index = i; } } else if (item == '&') { break; } i++; } string key = null; string value = null; if (index >= 0) { key = queryString.Substring(startIndex, index - startIndex); value = queryString.Substring(index + 1, (i - index) - 1); } else { key = queryString.Substring(startIndex, i - startIndex); } if (isEncoded) { result[MyUrlDeCode(key, encoding)] = MyUrlDeCode(value, encoding); } else { result[key] = value; } if ((i == (count - 1)) && (queryString[i] == '&')) { result[key] = string.Empty; } } } return result; } /// <summary> /// 解码URL. /// </summary> /// <param name="encoding">null为自动选择编码</param> /// <param name="str"></param> /// <returns></returns> private static string MyUrlDeCode(string str, Encoding encoding) { if (encoding == null) { Encoding utf8 = Encoding.UTF8; //首先用utf-8进行解码 string code = HttpUtility.UrlDecode(str.ToUpper(), utf8); //将已经解码的字符再次进行编码. string encode = HttpUtility.UrlEncode(code, utf8).ToUpper(); if (str == encode) encoding = Encoding.UTF8; else encoding = Encoding.GetEncoding("gb2312"); } return HttpUtility.UrlDecode(str, encoding); } /// <summary> /// 创建http请求 /// </summary> /// <param name="ClassName">方法名</param> /// <param name="sArray">参数</param> /// <returns></returns> public static string HttpPost(string ClassName, Dictionary<string, string> sArray) { var sb = new StringBuilder(); int i = 0; foreach (var sA in sArray) { i++; string value = sA.Value.ToString(); sb.Append(sA.Key).Append("=").Append(sA.Value); if (i != sArray.Count) sb.Append("&"); } string HttpUrl = string.Format("{0}{1}", ClassName, "?" + sb.ToString()); Encoding encoding = Encoding.UTF8; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(HttpUrl); request.Method = "POST"; request.Accept = "text/html, application/xhtml+xml, */*"; request.Timeout = 10000;//10秒超时 request.ContentType = "application/x-www-form-urlencoded"; //如果内容在BODY请示,加入下面 //byte[] buffer = encoding.GetBytes(body); //request.ContentLength = buffer.Length; //request.GetRequestStream().Write(buffer, 0, buffer.Length); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { return reader.ReadToEnd(); } } #endregion }