用产品思维设计API—— 安全,就只能用HTTPS?

Posted 北漂周

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用产品思维设计API—— 安全,就只能用HTTPS?相关的知识,希望对你有一定的参考价值。

用产品思维设计API(五)—— 安全,就只能用HTTPS?

前言

最近公司内部在重构项目代码,包括API方向的重构,期间遇到了很多的问题,不由得让我重新思考了下。
- 一个优雅的API该如何设计?
- 前后端分离之后,API真的解耦分离了吗?
- 不断的版本迭代,API的兼容性该如何做?

ps.这里所说的API仅为Web API,提供APP\\WEB开发使用。

年前,我司内部的接口已经进入了一个完全的重构阶段,参考了市面上各大平台的API和文档,自己也总结出了很多的心得。这里向大家分享一下,接下来一个月,我们向从下面几个方面向大家介绍一个优雅的API(至少我认为挺优雅)该如何设计。

  1. RESTful就是个骗局 (http://blog.csdn.net/yzzst/article/details/53775319)
  2. 数据解耦,才是前后分离的本质(http://blog.csdn.net/yzzst/article/details/53844590)
  3. 版本控制,没有你想的这么简单(http://blog.csdn.net/yzzst/article/details/54755077
  4. 随意定义错误码,你还在这样干?(http://blog.csdn.net/yzzst/article/details/54799971
  5. 安全,就只能用HTTPS?(http://blog.csdn.net/yzzst/article/details/54882346

ps. 打一个广告,公司内部现在在招聘各种技术岗位,Java、android、前端等,待遇保证能让你涨30%,有兴趣的朋友可以加韬哥的微信(微信号:stchou_zst),二维码在文章最后。


安全是一个老生常谈的问题,在API设计中也备受关注。但是,对于很多人的理解,Web API 的安全就是使用Https协议。世界上没有什么东西是绝对的,这里我们直接给出结论:

安全 ≠ HTTPS

如果还有朋友对于https协议一知半解的话,可以看一下我之前的博文:http://blog.csdn.net/yzzst/article/details/46693685


信息安全三要素

在数据传输中的三要素:
1. 保密性
2. 完整性
3. 可用性

API的安全判断和主要的攻击手段也是从这三个方便延伸出来,常见的有:
- API恶意调用,消耗系统资源(如登录、注册、验证码等等)——(不可用)
- 篡改数据,制造垃圾数据 ——(不可用)
- 使用Root设备,进行Https抓包 ——(不保密)
- 重放(Replay)攻击 ——(不完整)

那么我们设计API的时候,对应的防御手段也由此而来了:

  1. 对每一个API接口请求进行签名认证,防止使用fiddler等抓包工具轻易的抓包、篡改、提交等等。
  2. 加入时间戳,做频率时间验证。
  3. 对一些消耗性资源做频率限制,如:短信验证码下发同一个手机号每分钟仅允许1次
  4. 对于一些敏感数据再次加密。

API自签名

签名的目的是为了确定我们的API请求是来自于自己的客户端,例如对于下面这个接口而言

http://api.test.com/getOrder?query=中融&pageSize=10

所包含的信息虽然能够然接口正常使用,但信息太少无法保证这个请求来源的唯一性和没有必要的安全性,我们必须针对这个请求加入一个签名字段Sign

构造签名sign?

签名的过程是将请求参数串以及APP密钥根据一定签名算法生成的签名值,作为新的请求参数从而提高访问过程中的防篡改性。即,告诉服务器,你是谁?在什么时间?你想干什么?你的口令?

那么我们现在就定义几个字段表示这些数据:

操作对应字段说明
你是谁?accessId、accessKey每一个版本的客户端接入之前动态分配的,1. 做验证是计算使用。 2. 方便以后启用/停用任意一个api来源
在什么时间?timeStamp时间戳
你想干什么?/getOrder?query=中融&pageSize=10之前的原有操作
你的口令?sign一个不可逆算法,一般采用sha1或md5,

我们的Sign签名算法为:

Sign = HMAC_SHA1(accessKey + sourceRequest + timeStamp)

如这里我们已经获取有一个,

accessId=9999
accessKey=ABCDEFG

的Android客户端希望请求接口

/getOrder?query=中融&pageSize=10

Step1:获取当前时间戳

/getOrder?query=中融&pageSize=10&timeStap=1361431471

url编号后得到,请求源数据串(sourceRequst)

%2fgetOrder%3fquery%3d%e4%b8%ad%e8%9e%8d%26pageSize%3d10%26timeStap%3d1361431471

Step2:生成Sign

Sign = HMAC_SHA1(accessKey + sourceRequest + timeStamp)
Sign = 51856f01388a190a42f7fd7f73255240dfca7e97

Step3: 重新生产请求地址

/getOrder?query=中融&pageSize=10&timeStap=1361431471&accessId=9999&sign=51856f01388a190a42f7fd7f73255240dfca7e97

该设计优势

  • 可以根据timeStap对接口进行时间限制,如五分钟之内有效,如果修改时间必定会修改sign。
  • sign签名可以校验请求数据是否被篡改
  • 加入accessId,可以监控每一个api渠道来源的是否正常,动态启用/停用该渠道
  • 加密、解密速度快

该设计劣势

  • 整个sign的构造过程在客户端完成,对于客户端的防止逆向要求较高

频率限制

对于一些比较重要的资源接口,如:下发短信验证码、发送邮件、下单等,操作会消耗公司内部的系统资源和服务器资源,如果被其他人恶意调用的极有可能造成服务的不可用性,即常说的DDOS。

这个时候我们就必须对一些接口进行操作频率限制。可以按年、月、日、时、分、秒6个维度来做判断。如

接口说明使用频率
downVerfyCode下发验证码无登录操作。每个设备id,每分钟1次,每天200次
sendEmail发送邮件无登录操作。每个设备id,每天50次,每个月200次
createOrder下单登录后的操作。每个账户,每分钟10次

PS. 不同的接口频率判断标准不一样,根据具体的需求进行具体分析,对于没有登录就能够操作的接口,我们只能用设备id(DeviceId)做判断了。


敏感数据再次加密

  1. 使用SSL协议
  2. 对于敏感的数据,加入随即盐的方式存储以防范数据被篡改。
    如密码不要使用简单的MD5/SHA1,适当的可以
passwordEncrypt = MD5(password + phoneNumber  + 'chengyi')

写在后面,刚过完年,公司业务繁忙,重构任务重大,更新博客也慢了。希望大家多多包涵。

@author zhoushengtao(周圣韬)
@since 2017251754
@weixin stchou_zst
@blog http://blog.csdn.net/yzzst 

以上是关于用产品思维设计API—— 安全,就只能用HTTPS?的主要内容,如果未能解决你的问题,请参考以下文章

用产品思维设计API——RESTful就是个骗局

用产品思维设计API——数据解耦,才是前后分离的本质

用产品思维设计API——RESTful就是个骗局

用产品思维设计API——数据解耦,才是前后分离的本质

用产品思维设计API——版本控制,没有你想的这么简单

用产品思维设计API——版本控制,没有你想的这么简单