例如一个URL如下http://xx.xx?key=value&key=value 现在要加上签名验证
建议加上时间戳参数防止一个接口在短时间内被多次请求
然后URL就变成了了http://xx.xx?key=value&key=value×tamp=时间戳
sign我这里用MD5加密
前端获取sign方法
将要提交的参数提取出来将&符号去掉然后把参数排序,将排序后的参数拼接成一个字符串并且加上后端给的秘钥,然后在使用MD5加密就生成了sign
然后URL就变成了了http://xx.xx?key=value&key=value×tamp=时间戳&sign=签名
现在就可以提交了。
我们后端接请求后将所有参数放入一个字典,记得将sign参数移除,也可以在存放字典的时候就排除掉sign参数。
然后将字典的key排序,然后遍历字典将参数拼接成一个字符串并在末尾加上秘钥。
例如key1=value+key2=value+秘钥 这里的时间戳也算key,value。
具体代码如下
/// <summary>
/// 获取签名
/// </summary>
/// <param name="keyValues">URL参数</param>
/// <param name="secret">秘钥</param>
/// <returns></returns>
public static string GetSign(Dictionary<string, string> keyValues, string secret)
{
keyValues.Remove("sign");
var orderkeyValues = keyValues.Keys.OrderBy(x => x);
StringBuilder builder = new StringBuilder();
foreach (var item in keyValues)
{
builder.Append($"{item.Key}={item.Value}");
}
builder.Append(secret);
var md5 = MD5.Create();
var bytes = Encoding.Default.GetBytes(builder.ToString());
var md5bytes = md5.ComputeHash(bytes);
return BitConverter.ToString(md5bytes).Replace("-","");
}
public static (bool,string) verifySign(Dictionary<string, string> keyValues)
{
var pasttime = System.Configuration.ConfigurationManager.AppSettings["pastdate"];
var secret = System.Configuration.ConfigurationManager.AppSettings["secret"];
var timestamp = keyValues["timestamp"];
var sign = keyValues["sign"];
if (timestamp != ""&& timestamp != null)
{
DateTime? date = webservice.timestamp.StampToDateTime(timestamp);
if (date is null) //时间转换失败
{
return (false, "时间戳转换失败");
}
else
{
DateTime time = DateTime.Now;
var pastdatetime = date?.AddMinutes(double.Parse(pasttime));
if (pastdatetime > time)
{
string gensign = GetSign(keyValues, secret);
if (gensign == sign)
{
return (true, "");
}
else
{
return (false, "签名验证失败");
}
}
else
{ //签名过期
return (false, "签名过期");
}
}
}
return (false, "签名验证失败");
}