Asp中接⼝签名与验签常⽤⽅法
现在在程序开发中经常会⽤到第三⽅功能或数据,当我们调取第三⽅接⼝时,⾸先要做的就是要按照他们的规则进⾏验签通过后才可去使⽤。这也是出于安全⽅⾯的考虑,谁都不想⾃⼰的东西在⽹络中“裸奔”,哈哈。经常⽤的第三⽅如⽀付,第三⽅登录,⽀付宝⽀付等当然还有⼀些短信接⼝,⾝份验证接⼝等,⽽我们⾃⼰的程序对外开放时也会经常⽤到如⾃⼰写的Webapi接⼝等。下⾯就说⼀下常⽤的签名,验签的⽅式。
_appId:应⽤唯⼀标识
_appKey:加密key,⽤来校验应⽤的合法化
⼀,签名⼯具类
public class SignUtils
{
//编码格式字符串转数组工具类的方法
private static string inputCharset = "utf-8";
///<summary>
///签名字符串
///</summary>
///<param name="prestr">需要签名的字符串</param>
///<param name="key">密钥</param>
///<returns>签名结果</returns>
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();
}
///<summary>
///验证签名
///</summary>
/
//<param name="prestr">需要签名的字符串</param>
///<param name="sign">签名结果</param>
///<param name="key">密钥</param>
///<returns>验证结果</returns>
public static bool Verify(string prestr, string sign, string key)
{
string mysign = Sign(prestr, key);
if (mysign == sign)
{
return true;
}
return false;
}
///<summary>
///⽣成请求时的签名
///</summary>
///<param name="sPara">请求给⽀付宝的参数数组</param>
///<param name="key"></param>
///<returns>签名结果</returns>
public static string BuildSign(Dictionary<string, string> sPara, string key)
{
//把数组所有元素,按照“参数=参数值”的模式⽤“&”字符拼接成字符串
string prestr = CreateLinkString(sPara);
//把最终的字符串签名,获得签名结果
var mysign = Sign(prestr, key);
return mysign;
}
///<summary>
///把数组所有元素,按照“参数=参数值”的模式⽤“&”字符拼接成字符串
///</summary>
///<param name="dicArray">需要拼接的数组</param>
///<returns>拼接完成以后的字符串</returns>
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();
}
/
//<summary>
///把数组所有元素,按照“参数=参数值”的模式⽤“&”字符拼接成字符串,并对参数值做urlencode
///</summary>
///<param name="dicArray">需要拼接的数组</param>
///<param name="code">字符编码</param>
///<returns>拼接完成以后的字符串</returns>
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();
}
///<summary>
///除去数组中的空值和签名参数并以字母a到z的顺序排序
///</summary>
///<param name="dicArrayPre">过滤前的参数组</param>
/
//<returns>过滤后的参数组</returns>
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;
}
View Code
⼀,签名
将传递参数放到SortedDictionary中进⾏操作
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);
View Code
⼆,验签
Webapi中验签代码
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<JObject>(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))
{
//验签失败
}
}
///<summary>
///定义HttpResponseMessage
///</summary>
///<param name="actionContext">HttpActionContext</param>
///<param name="result">ResultMessage api结果返回类型</param>
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");        }
///<summary>
///验签
///</summary>
///<returns>成功返回true</returns>
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;
}
///<summary>
///检查key
///</summary>
///<returns></returns>
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;
}
View Code

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。