现在在程序开发中经常会用到第三方功能或数据,当我们调取第三方接口时,首先要做的就是要按照他们的规则进行验签通过后才可去使用。这也是出于安全方面的考虑,谁都不想自己的东西在网络中“裸奔”,哈哈。经常用的第三方如微信支付,第三方登录,支付宝支付等当然还有一些短信接口,身份验证接口等,而我们自己的程序对外开放时也会经常用到如自己写的Webapi接口等。下面就说一下常用的签名,验签的方式。
_appId:应用唯一标识
_appKey:加密key,用来校验应用的合法化
一,签名工具类
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
public class SignUtils { //编码格式 private static string inputCharset = "utf-8"; ////// 签名字符串 /// /// 需要签名的字符串 /// 密钥 /// 签名结果 public static string Sign(string prestr, string key) { StringBuilder sb = new StringBuilder(32); prestr = prestr + key; MD5 md5 = new MD5CryptoServiceProvider(); byte[] t = md5.ComputeHash(Encoding.GetEncoding(inputCharset).GetBytes(prestr)); for (int i = 0; i < t.Length; i++) { sb.Append(t[i].ToString("x").PadLeft(2, '0')); } return sb.ToString(); } /// /// 验证签名 /// /// 需要签名的字符串 /// 签名结果 /// 密钥 /// 验证结果 public static bool Verify(string prestr, string sign, string key) { string mysign = Sign(prestr, key); if (mysign == sign) { return true; } return false; } /// /// 生成请求时的签名 /// /// 请求给支付宝的参数数组 /// /// 签名结果 public static string BuildSign(Dictionary<string, string> sPara, string key) { //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 string prestr = CreateLinkString(sPara); //把最终的字符串签名,获得签名结果 var mysign = Sign(prestr, key); return mysign; } /// /// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 /// /// 需要拼接的数组 /// 拼接完成以后的字符串 public static string CreateLinkString(Dictionary<string, string> dicArray) { StringBuilder prestr = new StringBuilder(); foreach (KeyValuePair<string, string> temp in dicArray) { prestr.Append(temp.Key + "=" + temp.Value + "&"); } //去掉最後一個&字符 int nLen = prestr.Length; prestr.Remove(nLen - 1, 1); return prestr.ToString(); } /// /// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode /// /// 需要拼接的数组 /// 字符编码 /// 拼接完成以后的字符串 public static string CreateLinkStringUrlencode(Dictionary<string, string> dicArray, Encoding code) { StringBuilder prestr = new StringBuilder(); foreach (KeyValuePair<string, string> temp in dicArray) { prestr.Append(temp.Key + "=" + HttpUtility.UrlEncode(temp.Value, code) + "&"); } //去掉最後一個&字符 int nLen = prestr.Length; prestr.Remove(nLen - 1, 1); return prestr.ToString(); } /// /// 除去数组中的空值和签名参数并以字母a到z的顺序排序 /// /// 过滤前的参数组 /// 过滤后的参数组 public static Dictionary<string, string> FilterPara(SortedDictionary<string, string> dicArrayPre) { Dictionary<string, string> dicArray = new Dictionary<string, string>(); foreach (KeyValuePair<string, string> temp in dicArrayPre) { if (temp.Key.ToLower() != "sign" && !string.IsNullOrEmpty(temp.Value)) { dicArray.Add(temp.Key, temp.Value); } } return dicArray; }
一,签名
将传递参数放到SortedDictionary中进行操作
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
var dic = new SortedDictionary<string, string>(); var parameters = context.ApiActionDescriptor.Parameters; foreach (var apiParameterDescriptor in parameters) { var value = apiParameterDescriptor.Value; if (value.GetType() != typeof(string) && value.GetType() != typeof(int)&&value.GetType()!=typeof(long)) { var properties = value.GetType().GetProperties(); foreach (var propertyInfo in properties) { var val = value.GetType().GetProperty(propertyInfo.Name)?.GetValue(value); if (val != null) { dic.Add(propertyInfo.Name, val.ToString()); } } } else { dic.Add(apiParameterDescriptor.Name, apiParameterDescriptor.Value.ToString()); } } dic.Add("appid", _appId); //计算sign var sortDic = SignUtils.FilterPara(dic); var newsign = SignUtils.BuildSign(sortDic, _appKey); context.RequestMessage.AddUrlQuery("appid", _appId); context.RequestMessage.AddUrlQuery("sign", newsign);
二,验签
Webapi中验签代码
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) { //禁用ajax请求 var request = HttpContext.Current.Request; var headers = request.Headers; if (headers.AllKeys.Contains("X-Requested-With") && headers["X-Requested-With"] == "XMLHttpRequest") { Failed(actionContext, ResultMessage.Error("不支持ajax请求")); return; } //获取参数 var dic = new SortedDictionary<string, string>(); var streamReader = new StreamReader(request.InputStream); var result = streamReader.ReadToEnd(); if (!string.IsNullOrWhiteSpace(result)) { var value = JsonConvert.DeserializeObject(result); foreach (var property in value.Properties()) { dic.Add(property.Name, value.GetValue(property.Name).ToString()); } } if (request.Form.AllKeys.Length > 0) { foreach (var paramKey in request.Form.AllKeys) { dic.Add(paramKey, request.Form[paramKey]); } } if (request.QueryString.AllKeys.Length > 0) { foreach (var paramKey in request.QueryString.AllKeys) { dic.Add(paramKey, request.QueryString[paramKey]); } } ////验签 if (!CheckSign(actionContext, dic)) { //验签失败 } } /// /// 定义HttpResponseMessage /// /// HttpActionContext /// ResultMessage api结果返回类型 private void Failed(HttpActionContext actionContext, ResultMessage result) { actionContext.Response = actionContext.Response ?? new HttpResponseMessage(); actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(result), Encoding.UTF8, "application/json"); } /// /// 验签 /// /// 成功返回true private bool CheckSign(HttpActionContext actionContext, SortedDictionary<string, string> dic) { var appKey = ConfigHelper.GetConfigString("apiAppKey"); //检查appid if (!CheckKey(actionContext, dic, "appid", out var appId)) { return false; } /* * 此处直接声明了一个AppInfo的对象,实际开发中,要根据appId获取对应的appInfo信息,如下: * var appInfo= appInfoService.GetAppInfo(appId); */ //var appInfo = _appInfoService.GetAppInfo(appId); //if (appInfo == null) //{ // Failed(actionContext, ResultMessage.Error(ResultEnum.AppNotExists)); // return false; //} //检查sign if (!CheckKey(actionContext, dic, "sign", out var sign)) { return false; } dic.Remove("sign"); //计算sign var sortDic = SignUtils.FilterPara(dic); //var newsign = SignUtils.BuildSign(sortDic, appInfo.AppKey); var newsign = SignUtils.BuildSign(sortDic, appKey); //zKmxa_vyJHHUfNGoF85hXHSS5mq3tfwEYjyLMxiMCvo if (newsign != sign) { Failed(actionContext, ResultMessage.Error(ResultEnum.InvalidSign)); return false; } return true; } /// /// 检查key /// /// private bool CheckKey(HttpActionContext actionContext, SortedDictionary<string, string> dic, string key, out string value) { value = null; if (!dic.ContainsKey(key)) { Failed(actionContext, ResultMessage.ErrorFormat(ResultEnum.LossRequiredParams, key)); return false; } value = dic[key]; if (string.IsNullOrEmpty(value)) { Failed(actionContext, ResultMessage.ErrorFormat(ResultEnum.InvalidParams, key)); return false; } return true; }