最近公司有几个项目需要开发手机客户端,服务器端选用WebApi,那么如何保证手机客户端在请求服务器端时数据不被篡改,如何保证一个http请求的失效机制,下面总结一下我们在项目中针对这两个问题的解决方案。

基本思路如下:

  用户在成功登陆app客户端之后,手机客户端向服务器端发出的所有的http请求在请求头(HttpHeader)上都会带上下面三个参数:1、Uid(用户ID),2、Ts(时间戳),3、Sign(签名)。其中Ts是当前时间减去1970-1-1得到的10位的时间时间戳数字,Sign是接口中所有http请求参数与Uid、Ts经过MD5加密后得到的一个字符串。

具体实现如下(客户端的实现,手机客户端生成下面两个参数的思路是一样的):

1、Ts时间戳

Ts参数可以保证请求的时效性,在手机客户端生成的Ts,在服务器端验证一下,保证请求是在我们规定的时间段内,具体代码如下:

(1)、生成Ts(C#)代码如下,Andriod和IOS可以同理生成

 /// <summary>
        /// 获取十位的时间戳
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public string GenerateTimeStamp(DateTime dt)
        {
            // Default implementation of UNIX time of the current UTC time  
            TimeSpan ts = dt.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }  

(2)、服务器端端验证Ts代码如下,我们规定从手机客户端发到服务器端的请求有效期为5分钟,时间戳参数是跟在Http请求头中

//获取请求头信息
            var requestHeader = HttpContext.Current.Request.Headers;
           
            //10位时间戳
            var Ts = requestHeader.Get("Ts");
            //验证Ts是否合法(请求时间有效时间为:加减5分钟)
            var ts = Ts;//10位时间戳
            if (ts.Length != 10)
            {
                var resp = Request.CreateResponse<string>(HttpStatusCode.OK, "请求已过期", "application/json"); ;

                throw new HttpResponseException(resp);
            }
            var tsDate = ComHelper.ConvertIntDateTime(ts.ToString());
            if (tsDate > DateTime.Now.AddMinutes(5) || tsDate < DateTime.Now.AddMinutes(-5))
            {
                var resp = Request.CreateResponse<string>(HttpStatusCode.OK, "请求已过期", "application/json"); ;

                throw new HttpResponseException(resp);
            }

(3)、ComHelper公共类代码如下

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;

namespace OpenAPITest.App_Start
{
    public class ComHelper
    {
        /// <summary>
        /// 获取post/get集合
        /// </summary>
        /// <param name="ignoreCase">true 不区分大小写,统一返回小写  false 区分大小写</param>
        /// <returns></returns>
        public static SortedDictionary<string, string> GetRequestSortDic(bool ignoreCase)
        {
            int i = 0;
            SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
            NameValueCollection coll;
            //Load Form variables into NameValueCollection variable.
            coll = HttpContext.Current.Request.Form;

            //coll = HttpContext.Current.Request.Params;

            // Get names of all forms into a string array.
            String[] requestItem = coll.AllKeys;
            for (i = 0; i < requestItem.Length; i++)
            {
                if (ignoreCase)
                    sArray.Add(requestItem[i].ToLower(), GetString(requestItem[i]));
                else
                    sArray.Add(requestItem[i], GetString(requestItem[i]));
            }

            coll = HttpContext.Current.Request.QueryString;
            requestItem = coll.AllKeys;
            for (i = 0; i < requestItem.Length; i++)
            {
                if (ignoreCase)
                    sArray.Add(requestItem[i].ToLower(), GetString(requestItem[i]));
                else
                    sArray.Add(requestItem[i], GetString(requestItem[i]));
            }

            return sArray;
        }
        /// <summary>
        /// 从当前环境中获取
        /// </summary>
        /// <param name="name"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static string GetString(string name)
        {
            string res = "";
            var v = HttpContext.Current.Request[name];
            if (v != null)
            {
                res = v.ToString();
            }
            return res;
        }

        /// <summary>
        /// 时间戳转为C#格式时间
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <returns></returns>
        public static DateTime ConvertIntDateTime(string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime); return dtStart.Add(toNow);
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="str">原串</param>
        /// <param name="code">加密位</param>
        /// <returns></returns>
        public static string ToMD5(string str)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower();
        }

        /// <summary>
        /// 获取Sign
        /// </summary>
        /// <param name="inputPara"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string GetResponseMysign(SortedDictionary<string, string> inputPara, string privateKey)
        {
            string fullstring = GetPostStrings(inputPara, "_sign") + privateKey;
            return ToMD5(fullstring);
        }
        private static string GetPostStrings(SortedDictionary<string, string> inputPara, string excepted)
        {
            Dictionary<string, string> sPara = new Dictionary<string, string>();

            //过滤空值、sign与sign_type参数
            foreach (KeyValuePair<string, string> temp in inputPara)
            {
                if (temp.Key.ToLower() != excepted && temp.Value != "" && temp.Value != null)
                {
                    sPara.Add(temp.Key.ToLower(), temp.Value);
                }
            }

            //获得签名结果
            StringBuilder prestr = new StringBuilder();
            foreach (KeyValuePair<string, string> temp in sPara)
            {
                prestr.Append(temp.Key + "=" + temp.Value + "&");
            }

            //去掉最後一個&字符
            int nLen = prestr.Length;
            if (nLen > 1)
                prestr.Remove(nLen - 1, 1);
            return prestr.ToString();
        }

        /// <summary>
        /// 获取十位的时间戳
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string GenerateTimeStamp(DateTime dt)
        {
            // Default implementation of UNIX time of the current UTC time  
            TimeSpan ts = dt.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }  

    }
}
ComHelper

相关文章:

  • 2022-02-25
  • 2022-01-19
  • 2021-11-25
  • 2021-06-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-03
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-11
  • 2021-06-09
相关资源
相似解决方案