博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)
阅读量:5967 次
发布时间:2019-06-19

本文共 6386 字,大约阅读时间需要 21 分钟。

原文:http://www.cnblogs.com/codeon/p/6123863.html#3580351

1.完全开放的接口

有没有这样的接口,谁都可以调用,谁都可以访问,不受时间空间限制,只要能连上互联网就能调用,毫无安全可言。

实话说,这样的接口我们天天都在接触,你查快递,你查天气预报,你查飞机,火车班次等,这些都是有公共的接口。

我把这称之为裸奔时代。代码如下:

///         /// 接口对外公开        ///         /// 
[HttpGet] [Route("NoSecure")] public HttpResponseMessage NoSecure(int age) { var result = new ResultModel() { ReturnCode = 0, Message = string.Empty, Result = string.Empty }; var dataResult = stulist.Where(T => T.Age == age).ToList(); result.Result = dataResult; return GetHttpResponseMessage(result); }

2.接口参数加密(基础加密)

 你写个接口,你只想让特定的调用方使用,你把这些调用的人叫到一个小屋子,给他们宣布说我这里有个接口只打算给你们用,我给你们每人一把钥匙,你们用的时候拿着这把钥匙即可。

这把钥匙就是我上文说到的参数加密规则,有了这个规则就能调用。

这有安全问题啊,这里面的某个成员如果哪个不小心丢了钥匙或者被人窃取,掌握钥匙的人是不是也可以来掉用接口了呢?而且他可以复制很多钥匙给不明不白的人用。

相当于有人拿到了你的请求链接,如果业务没有对链接唯一性做判断(实际上业务逻辑通常不会把每次请求的加密签名记录下来,所以不会做唯一性判断),就会被重复调用,有一定安全漏洞,怎么破?先看这个场景的代码,然后继续往下看!

///         /// 接口加密        ///         /// 
[HttpGet] [Route("SecureBySign")] public HttpResponseMessage SecureBySign([FromUri]int age, long _timestamp, string appKey, string _sign) { var result = new ResultModel() { ReturnCode = 0, Message = string.Empty, Result = string.Empty }; #region 校验签名是否合法 var param = new SortedDictionary
(new AsciiComparer()); param.Add("age", age.ToString()); param.Add("appKey", appKey); param.Add("_timestamp", _timestamp.ToString()); string currentSign = SignHelper.GetSign(param, appKey); if (_sign != currentSign) { result.ReturnCode = -2; result.Message = "签名不合法"; return GetHttpResponseMessage(result); } #endregion var dataResult = stulist.Where(T => T.Age == age).ToList(); result.Result = dataResult; return GetHttpResponseMessage(result); }

3.接口参数加密+接口时效性验证(一般达到这个级别已经非常安全了)

继上一步,你发现有不明不白的人调用你的接口,你很不爽,随即把真正需要调用接口的人又叫来,告诉他们每天给他们换一把钥匙。和往常一样,有个别伙伴的钥匙被小偷偷走了,小偷煞费苦心,经过数天的踩点观察,准备在一个月黑风高的夜晚动手。拿出钥匙,捣鼓了半天也无法开启你的神圣之门,因为小偷不知道你天天都在换新钥匙。

小偷不服,经过一段时间琢磨,小偷发现了你们换钥匙的规律。在一次获得钥匙之后,不加思索,当天就动手了,因为他知道他手里的钥匙在第二天你更换钥匙后就失效了。

结果,小偷如愿。怎么破?先看这个场景的代码,然后继续往下看!

///         /// 接口加密并根据时间戳判断有效性        ///         /// 
[HttpGet] [Route("SecureBySign/Expired")] public HttpResponseMessage SecureBySign_Expired([FromUri]int age, long _timestamp, string appKey, string _sign) { var result = new ResultModel() { ReturnCode = 0, Message = string.Empty, Result = string.Empty }; #region 判断请求是否过期---假设过期时间是20秒 DateTime requestTime = GetDateTimeByTicks(_timestamp); if (requestTime.AddSeconds(20) < DateTime.Now) { result.ReturnCode = -1; result.Message = "接口过期"; return GetHttpResponseMessage(result); } #endregion #region 校验签名是否合法 var param = new SortedDictionary
(new AsciiComparer()); param.Add("age", age.ToString()); param.Add("appKey", appKey); param.Add("_timestamp", _timestamp.ToString()); string currentSign = SignHelper.GetSign(param, appKey); if (_sign != currentSign) { result.ReturnCode = -2; result.Message = "签名不合法"; return GetHttpResponseMessage(result); } #endregion var dataResult = stulist.Where(T => T.Age == age).ToList(); result.Result = dataResult; return GetHttpResponseMessage(result); }

4.接口参数加密+时效性验证+私钥(达到这个级别安全性固若金汤)

 继上一步,你发现道高一尺魔高一丈,仍然有偷盗事情发生。咋办呢?你打算下血本,给每个人配一把钥匙的基础上,再给每个人发个暗号,即使钥匙被小偷弄去了,小偷没有暗号,任然无法如愿,而且这样很容易定位是谁的暗号泄漏问题,找到问题根源,只需要给当前这个人换下钥匙就行了,不用大动干戈。

但这个并不是万无一失的,因为钥匙毕竟还有可能被小偷搞到。代码如下:

///         /// 接口加密并根据时间戳判断有效性而且带着私有key校验        ///         /// 
[HttpGet] [Route("SecureBySign/Expired/KeySecret")] public HttpResponseMessage SecureBySign_Expired_KeySecret([FromUri]int age, long _timestamp, string appKey, string _sign) { //key集合,这里随便弄两个测试数据 //如果调用方比较多,需要审核授权,根据一定的规则生成key把这些数据存放在数据库中,如果功能扩展开来,可以针对不同的调用方做不同的功能权限管理 //在调用接口时动态从库里取,每个调用方在调用时带上他的key,调用方一般把自己的key放到网站配置中 Dictionary
keySecretDic = new Dictionary
(); keySecretDic.Add("key_zhangsan", "D9U7YY5D7FF2748AED89E90HJ88881E6");//张三的key, keySecretDic.Add("key_lisi", "I9O6ZZ3D7FF2748AED89E90ZB7732M9");//李四的key var result = new ResultModel
() { ReturnCode = 0, Message = string.Empty, Result = string.Empty }; #region 判断请求是否过期---假设过期时间是20秒 DateTime requestTime = GetDateTimeByTicks(_timestamp); if (requestTime.AddSeconds(20) < DateTime.Now) { result.ReturnCode = -1; result.Message = "接口过期"; return GetHttpResponseMessage(result); } #endregion #region 根据appkey获取key值 string secret = keySecretDic.Where(T => T.Key == appKey).FirstOrDefault().Value; #endregion #region 校验签名是否合法 var param = new SortedDictionary
(new AsciiComparer()); param.Add("age", age.ToString()); param.Add("appKey", appKey); param.Add("appSecret", secret);//把secret加入进行加密 param.Add("_timestamp", _timestamp.ToString()); string currentSign = SignHelper.GetSign(param, appKey); if (_sign != currentSign) { result.ReturnCode = -2; result.Message = "签名不合法"; return GetHttpResponseMessage(result); } #endregion var dataResult = stulist.Where(T => T.Age == age).ToList(); result.Result = dataResult; return GetHttpResponseMessage(result); }

5.接口参数加密+时效性验证+私钥+Https(我把这个级别称之为金钟罩,世间最安全莫过于此)

继上一步,我们给传输机制改为Https,这下小偷彻底懵逼了。那么问题来了,Https咋玩儿呢?可以在本地搭个环境,参考此文:

你可能感兴趣的文章
并查集hdu1232
查看>>
Mysql 监视工具
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
博客搬家了
查看>>
Python中使用ElementTree解析xml
查看>>
jquery 操作iframe、frameset
查看>>
解决vim中不能使用小键盘
查看>>
jenkins权限管理,实现不同用户组显示对应视图views中不同的jobs
查看>>
我的友情链接
查看>>
批量删除用户--Shell脚本
查看>>
Eclipse Java @Override 报错
查看>>
linux的日志服务器关于屏蔽一些关键字的方法
查看>>
mysql多实例实例化数据库
查看>>
javascript 操作DOM元素样式
查看>>
HBase 笔记3
查看>>
【Linux】Linux 在线安装yum
查看>>
Atom 编辑器系列视频课程
查看>>
[原][osgearth]osgearthviewer读取earth文件,代码解析(earth文件读取的一帧)
查看>>
使用dotenv管理环境变量
查看>>
温故js系列(11)-BOM
查看>>