MVC OR API的接口

MVC OR WEBAPI的接口安全

当我们开发一款App的时候,App需要跟后台服务进行通信获取或者提交数据。如果我们没有完善的安全机制则很容易被别用心的人伪造请求而篡改数据。
所以我们需要使用某种安全机制来保证请求的合法。现在最常用的办法是给每个http请求添加一个签名,服务端来验证签名的合法性,如果签名合法则执行响应的操作,如果签名非法则直接拒绝请求。

签名算法

签名算法一般都使用Hash散列算法,常用的有MD5,SHA系列算法。这些算法可以根据不同的输入,计算出不同的结果,而且碰撞的概率很低。
签名算法跟加密算法不是一回事。很多同学都会说使用MD5加密一下,其实这是错误的。签名算法不能恢复原来的数据,因为它本身并不包含原来数据的信息。
而加密方法不同,加密方法是可以根据加密结果重新推算出原来的数据的。
HMAC SHA作为一种更加安全的签名算法,使用一个Key来影响签名的结果。这样同样的输入配合不同的Key可以得出不同的签名,更加安全。

 public static string HmacSHA256(string secretKey,string plain)
        {
            var keyBytes = Encoding.UTF8.GetBytes(secretKey);
            var plainBytes = Encoding.UTF8.GetBytes(plain);

            using (var hmacsha256 = new HMACSHA256(keyBytes))
            {
                var sb = new StringBuilder();
                var hashValue = hmacsha256.ComputeHash(plainBytes);
                foreach (byte x in hashValue)
                {
                    sb.Append(String.Format("{0:x2}", x));
                }
                return sb.ToString();
            }
        }

签名的参数

有了签名算法,那么我们签名的内容哪里来呢?
一般我们使用http请求的queryString然后加上时间戳还有随机数来作为签名的参数。

 public static string MakeSignPlain(SortedDictionary<string,string> queryString,string time,string random )
        {
            var sb = new StringBuilder();
            foreach (var keyValue in queryString)
            {
                sb.AppendFormat("{0}={1}&", keyValue.Key, keyValue.Value);
            }
            if (sb.Length>1)
            {
                sb.Remove(sb.Length - 1, 1);
            }
            sb.Append(time);
            sb.Append(random);

            return sb.ToString().ToUpper();
        }

验证签名

验证签名就是简单的比较服务端生产的签名跟客户端生产的签名是否一直。
要注意的一点是最好验证下时间戳,跟服务端时间比较前后不能相差5分钟。这也是一个简单的防Replay Attack的手段。

 public static bool Valid(string requestSign,string signPlain,string time, string secretKey)
        {
            if (string.IsNullOrEmpty(time)||string.IsNullOrEmpty(requestSign)||string.IsNullOrEmpty(signPlain))
            {
                return false;
            }
            //is in range
            var now = DateTime.Now;
            long requestTime =0;
            if (long.TryParse(time,out requestTime))
            {
                var max = now.AddMinutes(5).ToString("yyyyMMddHHmmss");
                var min = now.AddMinutes(-5).ToString("yyyyMMddHHmmss");
                if (!(long.Parse(max) >= requestTime && long.Parse(min) <= requestTime))
                {
                    return false;
                }

            }
            else
            {
                return false;
            }

            //hashmac
            var sign = Encryption.HmacSHA256(secretKey, signPlain);

            return requestSign.Equals(sign, StringComparison.CurrentCultureIgnoreCase);
        }

ApiController基类

有了上面这些铺垫我们就可以在基类完成签名的验证了。客户端需要把上面提到的时间戳,随机数,签名和客户端的ID放入http请求的headers里面。
我们在基类的OnActionExecuting里取出这些数据组合成签名的参数,然后根据客户端ID获取签名的Key,然后使用同样的签名算法计算签名。并且比较客户端的签名跟服务端的签名是否一致。
这里就不演示了。

预防Replay Attack

预防重放攻击主要有两点:

  • 校验时间戳的范围
    时间戳跟服务器时间相差在一个合理的范围内视为合法。
  • 缓存签名
    每次请求都去判断下签名是否出现过。如果出现过则视为非法请求。
    因为有时间戳跟随机数的存在,所以理论上每次请求的签名是不可能重复的。

客户端调用

这里演示一下C#签名并且调用http接口的代码

 [TestMethod()]
        public void GetUserTest()
        {
            string url = "http://localhost:8090/api/test/GetUser";
            string userId = "A39891D4-6CEF-4538-A562-3A422CA9C17A";
            string appId = "100001";
            string secretKey = "M/vkPOWXgBa7GnRd73t7j+jsKfbZtb+f";
            string rumdon = Guid.NewGuid().ToString();
            string time = DateTime.Now.ToString("yyyyMMddHHmmss");

            //make signture plain text
            var sortDict = new SortedDictionary<string, string>()
            {
                {"userId",userId }
            };
            var signPlain = new StringBuilder();
            foreach (var keyValue in sortDict)
            {
                signPlain.AppendFormat("{0}={1}&", keyValue.Key, keyValue.Value);
            }
            if (signPlain.Length > 1)
            {
                //remove last &
                signPlain.Remove(signPlain.Length - 1, 1);
            }
            signPlain.Append(time);
            signPlain.Append(random);

            Console.WriteLine("sign plain:{0}", signPlain.ToString().ToUpper());
            //make sign
            var sign = Encryption.HmacSHA256(secretKey, signPlain.ToString().ToUpper());
            Console.WriteLine("sign:{0}", sign);

            string requestUrl = string.Format("{0}?{1}={2}", url, "userId", userId);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.Method = "GET";
            //add headers
            request.Headers.Add("time", time);
            request.Headers.Add("appId", appId);
            request.Headers.Add("random", random);
            request.Headers.Add("sign", sign);
            //
            //start request
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    var responseStream = response.GetResponseStream();
                    if (responseStream != null)
                    {
                        using (StreamReader reader = new StreamReader(responseStream))
                        {
                            var content = reader.ReadToEnd();

                            Console.WriteLine(content);
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                using (HttpWebResponse response = (HttpWebResponse)ex.Response)
                {
                    var responseStream = response.GetResponseStream();
                    if (responseStream != null)
                    {
                        using (StreamReader reader = new StreamReader(responseStream))
                        {
                            var content = reader.ReadToEnd();
                            Console.WriteLine(content);
                        }
                    }
                }
            }
        }
时间: 2024-10-13 04:06:22

MVC OR API的接口的相关文章

【转载】ASP.NET MVC Web API 学习笔记---联系人增删改查

本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系人 说明:为了方便数据不使用真正的数据库,而是通过内存数据模拟 1.       Web API中包含的方法 Action HTTP method Relative URI GetAllContact GET /api/contact GetContact GET /api/contact /id

改变mvc web api 支持android ,ios ,ajax等方式跨域调用

公司一个移动后端的项目用到了 webapi 项目搭建到外网环境共app开发者调用测试接口时遇到了一个问题 接口不允许跨域调用 .查阅资料明白 同源策略原则根据请求报头值 Origin 与回应报头值 Access-Control-Allow-Origin 来判断是否允许调用 解决方法 1.ajax使用jsonp jsonp 是通过请求参数中加入回调函数参数值.webapi 收到回调函数参数值返回数据不再是单纯的json,而是根据回调函数参数值 的js方法调用,这样就避免的同源策略 需要webapi

ABP 教程文档 1-1 手把手引进门之 AngularJs, ASP.NET MVC, Web API 和 EntityFramework(官方教程翻译版 版本3.2.5)含学习资料

本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 转载请注明出处:http://www.cnblogs.com/yabu007/  谢谢 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1-1 手把手引进门 1-2 进阶 1-3 杂项 (相关理论知识) 第一篇含两个步骤. 1-1-1 ASP.NET Core & Entity Framework Core 后端(内核)含两篇 ( 第一篇链接    

微信公众号API测试——接口调用频率限制

接口频率限制[1] 公众号调用接口并不是无限制的.为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制,当超过一定限制时,调用对应接口会收到如下错误返回码: {"errcode":45009,"errmsg":"api freq out of limit"} 各接口调用频率限制如下: 接口 每日限额 获取access_token 2000 自定义菜单创建 1000 自定义菜单查询 10000 自定义菜

Asp.net mvc web api 在项目中的实际应用

Asp.net mvc web api 在项目中的实际应用 前言:以下只是记录本人在项目中的应用,而web api在数据传输方面有多种实现方式,具体可根据实际情况而定! 1:数据传输前的加密,以下用到 微软自带的 Rijndael 类(关于Rijndael 的更多信息请参见MSDN),32位密钥加16对称算法初始化向量,代码如下: //简单定义一个实体类: public class User { public int Id { get; set; } public string Name { g

MVC web api 返回JSON的几种方式,JSON时间去T的几种方式。

MVC web api 返回JSON的几种方式 1.在WebApiConfig的Register中加入以下代码 1 config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 2.在WebApiConfig的Register中加入以下代码 1 config.Formatters.Remove(config.Formatters.XmlFormatter);

基于百度风云榜开发的API数据接口-为APP资讯资讯服务

是基于百度搜索风云榜采集的新闻信息,,该资讯会更好的体现人们关注的人多事件与热词 通过数据采集,同时发布相信的数据开放API接口 1.取得热词信息列表 如:api.yi18.net/top/list 2.取得热词信息详细 如:api.yi18.net/top/show?id=1 更多的API文档 doc.yi18.net/topwendang 数据镜像网站:  top.yi18.net API数据接口的免费开放,希望为更多的APP开发者提供更专业的数据 接口.为APP开发提供更简单的新闻热点板块

药品API免费接口开放-APP数据接口

药品直达 ( drug.yi18.net )是医药吧网(www.yi18.net) 旗下的药品信息网. 打造药品信息查询平台,提供最全的药品信息.用于药品功能,价格,说明书, 使用手册的简单介绍. 药品直达API ,主要开放药品信息.API提供主要是为了更好的数据开放,同时 API不仅提供APP调用,同时也可以支持网站调用.免费开放,永久支持! API文档地址:doc.yi18.net/drugwendang 药品API接口的开放,为APP提供专门的数据接口,就可以简单快速的创建 自己的APP应

[angularjs] MVC + Web API + AngularJs 搭建简单的 CURD 框架

MVC + Web API + AngularJs 搭建简单的 CURD 框架 GitHub 地址:https://github.com/liqingwen2015/Wen.MvcSinglePage 布局页的引用 <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/bootstrap.min.js"></script&g