当前位置 博文首页 > 编程哲学家的专栏:API接口安全设计

    编程哲学家的专栏:API接口安全设计

    作者:[db:作者] 时间:2021-07-09 19:01

    ? 前段时间写的《?API接口设计》中有粗略的谈了下API安全相关的东西,没有很深入的写API接口安全,所以这篇文章就重点谈一下【API接口安全】

    token机制

    对于简单的客户端身份验证一般都采用token机制,方便快捷,实现方式也很简单,复杂度也小,且安全性也很高,有很实用,这是众多API安全设计中“性价比”最高的方案。普遍用于表单提交、发送短信/邮箱验证码、反爬虫、商城下单、数据敏感隐私有安全性需要的接口...等。

    这种方式的弱点是最怕的别人拿到token,一般是爬模板拿到。对于这个弱点,我的应对方法是配合多种验证来加强防防护,如验证请求头Request Headers里面的host、referer、cookie,你也可以自己定义请求头来验证,比如常见的:authority:,还可以把token放进js里,在发请求之前的时候动态添加上,还可以配合md5参数签名来加强安全性,可将token也一并带进参数签名。

    客户端如何获取token的两种种方式:?服务器端返回token、与服务器端使用相同的加盐签名算法自己生成token。如果用第二种方式一定要做好代码混淆加密工作,不然就功亏一篑、前功尽弃。

    ?

    appid、appkey机制

    有些地方也叫client_id、client_secret,appidappkey和client_id、client_secret是一个意思,一个概念。这种解决方案在对安全性要求非常高的时候才会采用的一种方法,因为极其复杂 ,例如支付.

    给每个客户端分配一个appid和appkey,发请求的时候将appkey+参数+时间进行md5签名,得到signature,appkey的主要是用于参与签名算法,时间戳用于时效性验证,本次生成的这个signature可以使用多长时间,是1分钟还是半小时你自己定。请求的时候带着生成的signature+参数+时间戳+appid,服务端接收到请求后以同样的签名算法生成签名,并与当前发送过来的signature进行对比,如果不一致,说明参数被篡改过,直接返回错误标识。签名机制保证了数据不会被篡改,appid用于识别客户端的身份,appkey用于签名算法加盐,没有appkey签名永远无法通过。

    关于签名规则,这个你可以根据情况自己调整,签名算法和服务器签名算法一致就行,常见的有以下几种:

    • md5(appkey+参数+时间戳+appkey)=signature
    • md5(appkey+参数+时间戳+appid)=signature
    • md5(appkey+md5(参数)+时间戳+appkey)=signature
    • md5(appkey+参数key+参数val+时间戳+appkey)=signature
    • ......

    还有一个token+appkey+参数+时间戳的,这种相当于又增加了一层验证,还可以再配合上前面提到的host、referer,让接口安全程度达到固若金汤的级别,我个人觉得再加token的意义不是很大。

    安全需要更高的还有接口参数加密(注意不是参数签名,是参数加密,上面只是用参数来签名,但参数要是要明文传递),适合场景,公司内部两个项目组进行对接,为了防止接口被暴露和伪造访问,这个时候需要对参数进行加密处理,防止接口被其他外部人员调用,一般采用desc或者aes对称加密,约定好秘钥进行对接。一般采用desc或者aes对称加密,约定好秘钥进行对接.

    ?

    ?客户端安全

    ?在安全攻防中,保证客户端代码不被反编译、破解是尤为重要的,客户端代码里藏匿着与服务器端的交互方法、签名算法,客户端被反编译不但接口安全毁于一旦,可能还会暴露给攻击者服务器端防御最薄弱的环节。如果客户端安全没有做好即使你API接口安全做到再完善、再天衣无缝也无济于事,前面的努力全白费。假如骇客破解反编译客户端成功,就相当于釜底抽薪,前面的努力全白费,前功尽弃。

    这就像木桶定律,一只水桶能装多少水取决于它最短的那块木板 ?。一只木桶想盛满水,必须每块木板都一样平齐且无破损,如果这只桶的木板中有一块不齐或者某块木板下面有破洞,这只桶就无法盛满水。

    ?

    • web (b/s):

    对于b/s web类应用,重要的js文件一定要混淆加密(比如配合token签名算法类js代码、文件),目前市面上有很多提供js加密的软件、网站,有收费的,有免费的。虽不能保证100%不被破解,但一个可靠的js混淆加密至少能保证90%的概率的不会被破解。对于一些安全要求极为苛刻的项目可以使用一些收费的js加密服务,有些混淆加密甚至可以达到95%~98%,你还可以进行多次反复加密。加密后可以找专业的安全公司来进行逆行工程测试,这样做基本就可以保证客户的安全了,当黑客在想拿你网站的数据,他需要衡量一下你的数据是否真的值得花费那么多时间和精力,甚至钱。

    • ?moblie 、pc(c/s):

    对于分布式c/s客户端的形式最重要就是保护安装包不会被破解反编译,否则接口安全设计再完美也没用。混淆、加密、加固一个都不能少,做完之后可以自己反编译个工具测试一下,之后对安全要求十分苛刻的可以再找安全公司做专门的安全工作。

    不过由于token验证的方式比较简单直接,基本上不需要客户端做什么,反而对安全了许多,即使客户端被破解、反编译了都没什么。

    ?

    一般安全有如下几方面

    • 传输加密(对抗链路破解、保护数据不受流量审查监控,如果你用的是http明文传输,数据又没加密,那如果有敏感关键词很有可能还没到服务器那边,在传输过程中直接给你重定向,拦截请求。)
    • 数据加密(对抗协议破解、网络层面的监控)
    • 代码加密(隐藏算法、反调试...)

    为了不受网络、流量层面的监控,客户端与服务器端通信时要尽量使用https。

    ?实际项目中该采取哪种API安全设计方案?

    web端一般采用token、md5算法 签名加密参数 ,对生成加密算法的js文件进行混淆加密,对安全性要求苛刻的,可进行多次反复加密,或者直接用付费的js安全加密服务

    敏感性较高数据接口可以采用相对复杂的appid+appkey+md5算法参数签名,简单的用token,客户端加固加密混淆,对安全性要求极高找专业的安全公司来做客户端混淆加密。

    另外扯个题外话,md5是一种签名,base64是一种编码,但总有人将这两种与加密的概念、名称弄混,成为他们为加密,你一定听说过有人说“md5加密”、“base64加密”。

    总结:所有的安全措施都用上的话有时候难免太过复杂,在实际项目中需要根据自身情况、应用场景作出取舍,比如可以只使用签名机制就可以保证信息不会被篡改,或者定向提供服务的时候只用Token机制就可以了,如何取舍,全看项目实际情况和对接口安全性的要求。

    这里只谈安全设计方案,不写具体实现,具体的大家可以参考各自的的语言自己实现,编程思想、解决问题的思路是可以跨语言的,不依赖具体实现,依赖抽象才是优秀的开发者应有的职业素养,代码只不过是实现的工具而已,这背后的思想才是解决问题的核心,就如同西方已经去世几百年的哲学家们,他们思想如今依然在影响着世界。

    ?

    cs