最原始接口:public string GetProjectInfo(string latest_update_time);
修改后接口:public string GetProjectInfo(string latest_update_time, string appKey, string timeStamp, string nonce, string signature);
添加参数:
appKey 接口Key
appSecret 接口密钥
timeStamp 时间戳 毫秒
nonceStr 随机字符串
signature 加密字符串
解决三个接口安全问题:
1.保证参数不被篡改
2.保证访问的合法性
3.保证请求的唯一性,防止暴力访问
签名校验的原理就是appSecret 只有你知我知,通过加入appSecret 加密生成的签名无法破解,这样就可到达确保参数不被修改,因为服务端会通过相同的算法生成签名,如果和传过来的签名不一样则代表参数发生了改表
签名算法 比如:signature =MD5(appKey +timeStamp +nonceStr +appSecret )
时间戳+随机字符串就可以防止接口被同一个请求重复调用
服务端设置一个时效时间,比如十分钟,十分钟内请求合理,在判断nonceStr 随机字符串在服务端是否有缓存,有的话也代表请求失效
接口定义:
public string GetProjectInfo(string latest_update_time, string appKey, string timeStamp, string nonce, string signature);
/// <summary> /// 验证 /// </summary> /// <param name="latest_update_time"></param> /// <param name="appKey"></param> /// <param name="timeStamp"></param> /// <param name="nonce"></param> /// <param name="signature"></param> public void Verification(string latest_update_time, string appKey, string timeStamp, string nonce, string signature) { try { DateTime update_time = DateTime.MinValue; string appSecret = ""; //更新时间 if (StringUtil.isNotNullOrBlank(latest_update_time)) { if (!DateTime.TryParse(latest_update_time, out update_time)) { throw new Exception("参数latest_update_time格式不正确"); } } else { throw new Exception("参数latest_update_time不能为空"); } //appKey if (StringUtil.isNotNullOrBlank(appKey)) { if (appDic.ContainsKey(appKey)) { appSecret = appDic[appKey]; } else { throw new Exception("参数appKey不合法"); } } else { throw new Exception("参数appKey不能为空"); } //timeStamp时间戳 if (StringUtil.isNotNullOrBlank(timeStamp)) { long currentTimeStamp = Convert.ToInt64(GetTimeStamp()); //有效期60分钟 if (Math.Abs(currentTimeStamp - Convert.ToInt64(timeStamp)) > (60 * 60 * 1000)) { throw new Exception("参数timeStamp已过期"); } } else { throw new Exception("参数timeStamp不能为空"); } //随机字符串 if (StringUtil.isNotNullOrBlank(nonce)) { if (CacheHelper.GetCache(nonce) == null) { CacheHelper.SetCache(nonce, timeStamp, 10 * 60); } else { throw new Exception("参数nonce已使用"); } } else { throw new Exception("参数nonce不能为空"); } //signature签名 if (StringUtil.isNotNullOrBlank(signature)) { string signTempStr = appSecret + latest_update_time + appKey + timeStamp + nonce + appSecret; string signResult = GenerateMD5(signTempStr); if (signature != signResult) { throw new Exception("签名验证失败"); } } else { throw new Exception("参数signature不能为空"); } } catch (Exception) { throw; } } /// <summary> /// 获取时间戳 毫秒 /// </summary> /// <returns></returns> public static string GetTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalMilliseconds).ToString(); } /// <summary> /// Md5加密 32位小写 /// </summary> /// <param name="txt"></param> /// <returns></returns> public static string GenerateMD5(string str) { using (MD5 mi = MD5.Create()) { byte[] buffer = Encoding.Default.GetBytes(str); //开始加密 byte[] newBuffer = mi.ComputeHash(buffer); StringBuilder sb = new StringBuilder(); for (int i = 0; i < newBuffer.Length; i++) { sb.Append(newBuffer[i].ToString("x2")); } return sb.ToString(); } }