开放平台如何设计安全的对外接口
[提前声明]
文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章
写作不易,转载请注明,谢谢!
大数据代码案例地址: https://github.com/Mydreamandreality/sparkResearch
场景
开放平台需要提供对外的接口,保障数据安全和客户真实性
- 1、传输的数据加密
- 2、客户端的身份鉴别
- 3、签名机制防止数据被篡改
- 4、时间戳机制
- 5、限流、降权机制
- 6、黑名单
通过以上的设计,可以构建出一个基本的安全架构
详细设计
- 1、传输的数据加密
如果大家使用过wireshark
或者fiddler
之类的抓包工具,就知道数据在传输的过程中是很容易被抓包的,如果我们使用http
协议来传输我们的数据,就跟裸奔是一样的,明文数据全部暴露在了外面,所以成熟的解决方案是应该使用HTTPS
协议传输,在我们的http层和tcp层增加SSL加密层,对传输数据进行加解密,甚至一些不需要明文处理的数据,可以直接通过hash+盐或者其它不可逆的算法来对数据进行传输,验证只需要对比hash值即可
这里的不可逆也不是绝对的,一般来讲只能提高逆向的难度,比如彩虹表攻击,举个栗子: 一个密文你需要十年的时间才能逆向出来明文,对于防护方来说,这是可以接受的,所以在传统的安全对抗中,我们不能完全的低档攻击方,那这个时候换个思路,你可以攻破我,但你最少需要十年的时间
彩虹表攻击:
彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值、微缩图、摘要、指纹、哈希密文)而准备
- 2、客户端鉴权
我们随便找一个开放平台,在调用开放平台接口之前都需要先登录,然后再申请Appid和AppSerect,Appid的作用就是标识不同的租户,AppSerect是传输中实现加密功能的密钥,通过Appid和AppSerect生成对应的access_token传输给开放平台,开放平台服务端进行相关的验证,例如:验证该用户是否是黑名单用户,是否有权限使用该接口等等
钉钉开放平台中的做法是需要appid和appserect请求生成access_token,这个value由钉钉直接写入到租户业务系统的数据库中,租户请求需要携带access_token,有效时长为二十分钟,过期需要租户重新请求新的token
- 3、签名机制防止数据篡改
外网有https,其实数据是没必要再次签名的,但是我们要考虑到数据传输不只是经过外网,还有内网,在内网传输这个过程中的安全保障就需要签名机制
之前和钉钉合作开发的时候,是我们提供接口给钉钉客户端使用,所以需要我们用appid来申请公钥,钉钉用本次申请的公钥所对应的私钥对数据做数字签名,我们接收到请求后用公钥进行验签
- 4、时间戳机制
这样设想一下,我们的数据传输都是密文,也有数字签名来保障数据安全性,但是我抓到你的包后,我不管你的传输内容是什么,我可以直接复用本次请求,来拿到你的响应内容,所以我们需要额外的增加时间戳机制,来验证本次的请求是否为过期请求
时间戳机制可以和数字签名配合使用,例如在请求中增加RequestTimestamp字段,增加数字签名防止篡改,服务端收到租户的请求后公钥验签,进行时间戳的验证,如果该请求是当前时间五分钟之前的,则拒绝访问
- 5、限流、降权
访问我们的平台是需要用appid换取access_token的,这一步就可以过滤掉非正常用户的请求,但如果是正常用户,在一段时间内出现了频繁调用接口的行为,也需要做降权或者限流的策略
使用令牌桶算法或者借助Redis来实现限流算法,针对同一appid的限流
- 6、黑名单
如果正常用户产生了触发阈值的非法操作(比如:每分钟5次的恶意请求),此时我们应该增加黑名单机制,把该租户的appid加入至黑名单,下次请求直接拒绝,返回业务拒绝码