using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Text; using System.Web; using Znyc.Cloudcar.Admin.Commons.Cache; using Znyc.Cloudcar.Admin.Commons.Encrypt; using Znyc.Cloudcar.Admin.Commons.Entitys; using Znyc.Cloudcar.Admin.Commons.Extensions; using Znyc.Cloudcar.Admin.Commons.Json; using Znyc.Cloudcar.Admin.Commons.Options; namespace Znyc.Cloudcar.Admin.Commons.Helpers { /// /// 签名验证自定义类 /// public class SignHelper { /// /// 全局过滤器验证签名 /// /// /// public static CommonResult CheckSign(HttpContext httpContext) { CommonResult result = new CommonResult(); //从http请求的头里面获取参数 HttpRequest request = httpContext.Request; string appId = ""; //客户端应用唯一标识 string nonce = ""; //随机字符串 string signature = ""; //参数签名,去除空参数,按字母倒序排序进行Md5签名 为了提高传参过程中,防止参数被恶意修改,在请求接口的时候加上sign可以有效防止参数被篡改 long timeStamp; //时间戳, 校验5分钟内有效 try { appId = request.Headers["appId"].SingleOrDefault(); nonce = request.Headers["nonce"].SingleOrDefault(); timeStamp = Convert.ToInt64(request.Headers["timeStamp"].SingleOrDefault()); signature = request.Headers["signature"].SingleOrDefault(); } catch (Exception ex) { result.ErrCode = "40004"; result.ErrMsg = "签名参数异常:" + ex.Message; return result; } //appId是否为可用的AllowCacheApp allowCacheApp = VerifyAppId(appId); //if (allowCacheApp == null) //{ // result.ErrCode = "40004"; // result.ErrMsg = "AppId不被允许访问:" + appId; // return result; //} //判断timespan是否有效,请求是否超时 DateTime tonow = timeStamp.UnixTimeToDateTime(); int expires_minute = tonow.Minute - DateTime.Now.Minute; if (expires_minute > 5 || expires_minute < -5) { result.ErrCode = "40004"; result.ErrMsg = "接口请求超时"; return result; } //根据请求类型拼接参数 NameValueCollection form = HttpUtility.ParseQueryString(request.QueryString.ToString()); string data = string.Empty; if (form.Count > 0) { data = GetQueryString(form); } else { //request.EnableBuffering(); request.Body.Seek(0, SeekOrigin.Begin); Stream stream = request.Body; StreamReader streamReader = new StreamReader(stream); data = streamReader.ReadToEndAsync().Result; request.Body.Seek(0, SeekOrigin.Begin); } CacheHelper cacheHelper = new CacheHelper(); object reqtimeStampCache = cacheHelper.Get("request_" + timeStamp + nonce); if (reqtimeStampCache != null) { result.ErrCode = "40004"; result.ErrMsg = "无效签名"; return result; } TimeSpan expiresSliding = DateTime.Now.AddMinutes(120) - DateTime.Now; cacheHelper.Add("request_" + timeStamp + nonce, timeStamp + nonce, expiresSliding); //bool blValidate = Validate(timeStamp.ToString(), nonce, allowCacheApp.AppSecret, data, signature); //if (!blValidate) //{ // result.ErrCode = "40004"; // result.ErrMsg = "无效签名"; // return result; //} //else //{ result.ErrCode = "0"; result.Success = true; return result; //} } /// /// get请求查询参数, url上直接接参数时,通过此方法获取 /// /// 请求参数 /// public static string GetQueryString(NameValueCollection form) { //第一步:取出所有get参数 Dictionary parames = new Dictionary(); for (int f = 0; f < form.Count; f++) { string key = form.Keys[f]; if (key != null) { parames.Add(key, form[key]); } } // 第二步:把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parames); IEnumerator> dem = sortedParams.GetEnumerator(); // 第三步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(""); //签名字符串 if (parames == null || parames.Count == 0) { return query.ToString(); } while (dem.MoveNext()) { string key = dem.Current.Key; string value = dem.Current.Value; if (!string.IsNullOrEmpty(key)) { query.Append(key).Append(value); } } return query.ToString(); } /// /// 签名验证 /// /// 时间戳 /// 随机字符串 /// 客户端应用密钥 /// 接口参数内容 /// 当前请求内容的数字签名 /// public static bool Validate(string timeStamp, string nonce, string appSecret, string data, string signature) { string signStr = timeStamp + nonce + data + appSecret; string signMd5 = MD5Util.GetMD5_32(signStr); return signMd5 == signature; } /// /// 验证appId是否被允许 /// /// /// private static AllowCacheApp VerifyAppId(string appId) { AllowCacheApp allowCacheApp = new AllowCacheApp(); if (string.IsNullOrEmpty(appId)) { return allowCacheApp; } CacheHelper cacheHelper = new CacheHelper(); List list = cacheHelper.Get("AllowAppId").ToJson().ToList(); if (list.Count > 0) { allowCacheApp = list.Where(s => s.AppId == appId).FirstOrDefault(); } return allowCacheApp; } } }