MVC 统一验证Token demo - _小马哥 - 博客园

来源: 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();

        }
    }
}
复制代码

 

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏