zoukankan      html  css  js  c++  java
  • WebApi与手机客户端通信安全机制

    WebApi与手机客户端通信安全机制

    最近公司有几个项目需要开发手机客户端,服务器端选用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公共类代码如下

     ComHelper

    2、Sign签名

    (1)、sign的生成规则:服务器端接口中的所有参数+Uid+Ts,去除掉参数中值为空的参数后, 按照参数key值排序,用&链接,并全部转化为小写,然后用MD5加密,通过HttpHeader发送到服务器端接口。

    生成Sign大代码如下(C#),Android和IOS可以同理生成

    假如手机客户端请求的一个API接口为:http://weapi.com/order/getlist?StatusID=1&CarID=2&CityID=3&name=&key=222
    
    sign=md5(carid=2&cityid=3&key=222&statusid=1&ts=0123456789&uid=110)

    (2)、验证客户端的Sign,防止参数被修改

    复制代码
     //请求签名,客户端生成的签名
                var Sign = requestHeader.Get("Sign");
    //排序字典,按照key排序
                SortedDictionary<string, string> postValue = null;
                //获取请求中所有的参数
                postValue = ComHelper.GetRequestSortDic(true);
                postValue.Add("Uid", Uid);//API账户名称
                postValue.Add("Ts", Ts);//10位时间戳 
    
                string APIPrivateKey = "2D7E7C96-DAC5-4526-96C3-C60CDEC4B120";//客户端和手机端保持一致
                //服务器端生成的Sign
                string mysign = ComHelper.GetResponseMysign(postValue, APIPrivateKey);
                if (!Sign.Equals(mysign, StringComparison.InvariantCultureIgnoreCase))
                {
                    var resp = Request.CreateResponse<string>(HttpStatusCode.OK, "签名错误", "application/json"); ;
    
                    throw new HttpResponseException(resp);
                }
    复制代码

     3、模拟测试

     (1)C#模拟Http请求,代码如下

    复制代码
     //请求的API地址
                string url = "http://localhost:51942/api/Values/Get?StatusID=1&CarID=2&CityID=3&name=&key=1233";
                //生成Ts
                string Ts = ComHelper.GenerateTimeStamp(DateTime.Now);
                //SortedDictionary会自动按照key值排序
                SortedDictionary<string, string> sortDic = new SortedDictionary<string, string>();
                sortDic.Add("StatusID", "1");
                sortDic.Add("CarID", "2");
                sortDic.Add("CityID", "3");
                sortDic.Add("name", "");
                sortDic.Add("key", "1233");
                sortDic.Add("Uid","110");
                sortDic.Add("Ts", Ts);
                string APIPrivateKey = "2D7E7C96-DAC5-4526-96C3-C60CDEC4B120";//客户端和手机端保持一致,md5加密多使用了一个参数
                //获取Sign签名
                string Sign = ComHelper.GetResponseMysign(sortDic, APIPrivateKey);
                
                //发送请求
                System.Net.WebRequest wReq = System.Net.WebRequest.Create(url);
                wReq.Headers.Add("Uid", "110");
                wReq.Headers.Add("Ts", Ts);
                wReq.Headers.Add("Sign", Sign);
    
                System.Net.WebResponse wResp = wReq.GetResponse();
                System.IO.Stream respStream = wResp.GetResponseStream();
    
                using (System.IO.StreamReader reader = new System.IO.StreamReader(respStream, Encoding.UTF8))
                {
                    string res= reader.ReadToEnd();
                }
    复制代码

    (2)服务器端验证参数,参数验证写在BaseApiController.cs文件中,只要继承该类的都可以验证客户端传过来的参数

    复制代码
     public class ValuesController : BaseApiController
        {
            
            // GET api/values
            public IEnumerable<string> Get(string StatusID,string CarID,string CityID,string name, string key)
            {
                return new string[] { "value1", "value2" };
            }
    复制代码
     BaseApiController

     大家可以加我的QQ:530439142,一起交流成长

    WebApi与手机客户端通信安全机制 Eric.Chen 2015-10-20 18:23 阅读:758 评论:7  
     
    WebApi 服务监控 Eric.Chen 2015-01-22 11:28 阅读:1553 评论:2  
     
    webAPI 自动生成帮助文档 Eric.Chen 2014-08-22 10:50 阅读:1256 评论:4  
     
    MVC4+WebApi+Redis Session共享练习(下) Eric.Chen 2013-08-09 21:49 阅读:2156 评论:1  
     
    MVC4+WebApi+Redis Session共享练习(上) Eric.Chen 2013-08-08 20:41 阅读:3992 评论:12  
  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4899652.html
Copyright © 2011-2022 走看看