来源: MVC 统一验证Token demo – _小马哥 – 博客园
/// <summary> /// 获取token /// </summary> /// <param name="staffId"></param> /// <returns></returns> public JsonResult GetToken(string staffId) { ResultMsg resultMsg = null; //判断参数是否合法 if (string.IsNullOrEmpty(staffId)) { resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError; resultMsg.Info = "staffId不合法"; resultMsg.Data = new Token(); return Json(resultMsg, JsonRequestBehavior.AllowGet); } //插入缓存 Token token = (Token)HttpRuntime.Cache.Get(staffId); if (HttpRuntime.Cache.Get(staffId.ToString()) == null) { token = new Token(); token.StaffId = staffId; token.SignToken = Guid.NewGuid(); token.ExpireTime = DateTime.Now.AddDays(1); HttpRuntime.Cache.Insert(token.StaffId.ToString(), token, null, token.ExpireTime, TimeSpan.Zero); } //返回token信息 resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)StatusCodeEnum.Success; resultMsg.Info = ""; resultMsg.Data = token; return Json(resultMsg, JsonRequestBehavior.AllowGet); }
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Net; using System.Text; using System.Web; using System.Web.Mvc; using WebApplication_Token.Models; namespace WebApplication_Token.Controllers { public class VerificationTokenController : Controller { protected override void OnActionExecuting(ActionExecutingContext filterContext) { ResultMsg resultMsg = null; var request = Request; var method = request.HttpMethod; string staffid = string.Empty, timestamp = string.Empty, nonce = string.Empty, signature = string.Empty; if (!string.IsNullOrEmpty(request.Headers["staffid"])) { staffid = HttpUtility.UrlDecode(request.Headers.GetValues("staffid").FirstOrDefault()); } if (!string.IsNullOrEmpty(request.Headers["timestamp"])) { timestamp = HttpUtility.UrlDecode(request.Headers.GetValues("timestamp").FirstOrDefault()); } if (!string.IsNullOrEmpty(request.Headers["nonce"])) { nonce = HttpUtility.UrlDecode(request.Headers.GetValues("nonce").FirstOrDefault()); } if (!string.IsNullOrEmpty(request.Headers["signature"])) { signature = HttpUtility.UrlDecode(request.Headers.GetValues("signature").FirstOrDefault()); } //GetToken方法不需要进行签名验证 if (filterContext.ActionDescriptor.ActionName == "GetToken") { base.OnActionExecuting(filterContext); return; } //判断请求头是否包含以下参数 if (string.IsNullOrEmpty(staffid) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(signature)) { resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)HttpStatusCode.PartialContent; resultMsg.Info = "请求头缺少参数"; resultMsg.Data = new Token(); filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据 base.OnActionExecuting(filterContext); return; } //判断token是否有效 Token token = (Token)HttpRuntime.Cache.Get(staffid); string signtoken = string.Empty; if (token == null) { resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError; resultMsg.Info = "token为null"; resultMsg.Data = new Token(); filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据 base.OnActionExecuting(filterContext); return; } else { signtoken = token.SignToken.ToString(); } bool timespanvalidate = token.ExpireTime > Convert.ToDateTime(timestamp); if (!timespanvalidate) { resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)HttpStatusCode.PartialContent; resultMsg.Info = "token已过期"; resultMsg.Data = new Token(); filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据 base.OnActionExecuting(filterContext); return; } //根据请求类型拼接参数 NameValueCollection coll = Request.Form; string[] requestItem = coll.AllKeys; Dictionary<string, string> sArray = new Dictionary<string, string>(); int j = 0; for (j = 0; j < requestItem.Length; j++) { sArray.Add(requestItem[j], Request.Form[requestItem[j]]); } var queryStr = GetQueryString(sArray); var _signature = GetSingnature(timestamp, queryStr.Item1, staffid, signtoken, queryStr.Item2); if(signature!= _signature) { resultMsg = new ResultMsg(); resultMsg.StatusCode = (int)HttpStatusCode.PartialContent; resultMsg.Info = "token不合法"; resultMsg.Data = new Token(); filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据 base.OnActionExecuting(filterContext); return; } } /// <summary> /// 获取签名字符串 /// </summary> /// <param name="parames"></param> /// <returns></returns> public Tuple<string, string> GetQueryString(Dictionary<string, string> parames) { // 第一步:把字典按Key的字母顺序排序 IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parames); IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator(); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder("");//签名字符串 StringBuilder queryStr = new StringBuilder("");//url参数 if (parames == null || parames.Count == 0) { return new Tuple<string, string>("", ""); } while (dem.MoveNext()) { string key = dem.Current.Key; string value = dem.Current.Value; if (!string.IsNullOrEmpty(key)) { query.Append(key).Append(value); queryStr.Append("&").Append(key).Append("=").Append(value); } } return new Tuple<string, string>(query.ToString(), queryStr.ToString().Substring(1, queryStr.Length - 1)); } /// <summary> /// 根据参数计算签名 /// </summary> /// <param name="timeStamp">发起请求时的时间戳(单位:毫秒)</param> /// <param name="nonce">随机数</param> /// <param name="staffId">当前请求用户StaffId</param> /// <param name="signToken">signToken</param> /// <param name="data">参数url</param> /// <returns></returns> public string GetSingnature(string timeStamp, string nonce, string staffId,string signToken, string data) { var hash = System.Security.Cryptography.MD5.Create(); //拼接签名 var signStr = timeStamp + nonce + staffId + signToken + data; //将字符串中字符按升序排序 var sortStr = string.Concat(signStr.OrderBy(c => c)); var bytes = Encoding.UTF8.GetBytes(sortStr); //使用MD5加密 var md5Val = hash.ComputeHash(bytes); //把二进制转大写十六进制 StringBuilder result = new StringBuilder(); foreach (var c in md5Val) { result.Append(c.ToString("X2")); } return result.ToString().ToUpper(); } } }