接口被恶意调用中的恶意指的是不符合后端接口设定的调用逻辑,比如我的验证码接口是用来给我的注册用户发验证码的,每发一次我都要付费的,结果有人用我的接口去给一些手机号发验证码,把我的短信量耗没了,一些低级的程序员第一反应我网站被黑了,因为他的发送验证码代码都是百度上抄的,能发出去就行了,这时候出了问题一脸闷逼只能说个大概,好一点的会意识到是不是我的短信验证码接口有问题,排除了不是自己写的bug外,还是摸不着头绪,再好一点的会意识到我的接口是不是被恶意调用了,但是不知道怎么防。今天给大家说一下如何保证接口不被别人恶意调用
看问题要看本质,如果我们抓住了问题的本质,之后这一类问题对于我们来说就是一个问题,只是表面穿了不同的衣服而已
这个问题的本质是什么?首先它是如何调用我的接口的?这个接口比较特殊,在用户注册阶段,也就是这个用户的登录态并不在我们后端存储,换句坏说我们不知道这个用户的身份,意味着这个接口不需要用户权限就可以调用,也就是阿猫阿狗机器人脚本都可以过来调,那我写个循环发送接口请求的脚本,每秒跑一次,发给不同的手机,服务端能奈我何,有的人这时候会说服务端可以限制请求的频率,这是治标不治本,我可以换IP,或者把循环执行时间大于你的限制,没用的。其实这个被恶意调用的本质是篡改了我发送的数据,正常情况我的每次发送都是一个有手机号的真实用户,结果你伪造了一个别的手机号用户。那么我们的问题实际可以归纳为:如何防止数据不被篡改?没错就是签名机制,签名保证了我的数据没有任何人可以篡改,除非有人伪造了我的签名。那我们来看下签名为什么可以做到保护我的数据,做签名一般是用MD5函数对数据做签名,MD5保证了签名结果不可逆,理论上如果不知道我们的签名算法,是没办法拿到这个签名结果的,这时候有人篡改数据的时候,签名结果必然会变化,那服务端通过之前的算法校验签名结果,肯定和传输到后端的是不同的,这样我们可以挡掉这次攻击。我们用一个简单的签名算法看一下这个模式是如何工作的
整个情况是这样的
前提要有一个key秘钥(这里的key客户端和服务端要一致)
MD5('手机号'+'key') = 签名结果
客户端发送的数据:手机号+签名结果
服务端收到数据后计算 MD5('手机号'+'key') 是否等于传输过来的签名结果,在不知道签名算法包括key秘钥的情况下是没办法拿到签名结果的,也就是你换了手机号没法算出我的签名,也就没法攻击成功了
前面我们提到了有人会伪造签名,没错客户端这些签名算法包括key都是可以通过某些方法拿到的,强如微信的客户端签名算法别人都能找到,知道了这些当然可以伪造签名了,但是我们增加了攻击者的成本,正因为之前攻击我们是0成本的,现在有成本了他要考虑是否划算了,赔本的买卖别人是不干的,攻击者成本每多一层,我们就多一层安全。
知道了签名的意义,你就明白了为什么android的apk每次都需要签名了,为什么支付回调要签名了,说白了各种需要签名的地方都是因为改动了签名前面的数据会对我们造成非常大的损失