API的全称是应用编程接口(Application Programming Interface),这并不是一个新概念,在计算机操作系统出现的早期就已经存在了。在互联网时代,把网站的服务封装成一系列计算机易识别的数据接口开放出去,供第三方开发者使用,这种行为就叫做开放网站的API,与之对应的,所开放的API就被称作openAPI。
如果要将API开放出去提供给外部第三方调用,需要考虑些什么?如何搭建这样的系统呢?今天就来分析一下吧。
既然是开放平台,那么接口也就是开放给所有人。这里的所有人并不是谁都可以来调,至少需要在开放平台注册,是平台合法用户,然后注册应用,平台给你颁发一套appId和appSecert,请求时用来认证是不是合法用户。这是最基本的。
开放平台API处理流程为:安全校验、身份认证、鉴权、流控、加解密、基本参数检验,调用业务服务接口,结果包装,异常码转换,返回数据。
也叫重放攻击,指同一次请求再次发送到服务器。特指请求被不怀好意的人截获,再次发送给服务器进行重放攻击。
怎么预防?
1.请求参数加时间戳 每次发请求带上时间戳timestamp,服务端检验该字段值与服务器当前时间比较误差超过一分钟则拒绝请求。因为请求从发送,到服务端接收,有一定的时间差,大概不会超过一分钟吧!至于客户端服器时间与平台后端服务器时间不一致问题,服务端可以开放一个查询接口供客户端查询当前时间。
加时间戳能有效防止一部分重放,毕竟有60秒的窗口期,请求都认为有效。这部分重放怎么拦截?将请求的时间戳保存下来,校验存在认为重复请求,则拒绝。即便这样还是有两个问题: ①如果每次请求的时间戳都保存,对服务器来说是一笔很大的开销。 ②另外,timestamp参数很容易被发现是时间戳,伪造者也可以每次生成新的。
2.请求参数加nonce 基于以上两个漏洞,再增加一个参数nonce,参数值为随机数,具有唯一性。作为每次请求的唯一标识,参与生成签名sign,平台同样将nonce参数参与生成签名,并与客户端上送的签名sign值进行对比。因为nonce参数参与签名,即便被修改了,也无法通过校验。并且每次只需要存60秒的timestamp即可,大大减少了服务器开销。完美解决上述两个问题。
系统应对请求方的IP合法性进行校验,将认为存在不合法行为(单位时间内频繁请求、请求频繁报错,所以公司需要有相应的风控系统监测体系)的IP纳入到黑名单IP集合中。
前面提到要颁发appId、appSecret,这一步就来检验。
用户调认证接口,传appId和appSecret,平台校验成功后生成token,过期时间设置为20分钟(可根据自身业务调整),返回给用户。用户保存token,请求其它业务接口时传appId和token,平台校验token合法性,校验通过则放行。
token过期则需要用户重新获取新的token,并使用新的token调用业务接口。如果使业务不中断(中断是指,调用业务接口时告知token过期)那么用户需要定时更新token,例如每18分钟定时获取一次。
不同的用户可以开通不同的接口调用范围(如某些用户只能调A业务相关的API,某些用户只能调B业务相关的API)。
每个接口都有一个开关设置能否调用(平台在内管系统可操作) 系统级别的API开关(某些情况下关闭API对外开放能力) 不同用户状态下的接口调用范围的控制(审核中、已注销、用户违规被封禁、被冻结等)
流控是非常重要的一环,流控能有效保护系统。可以根据自身业务,服务器性能实现不同级别的流控,从不同纬度、不同粒度限流。例如:接口级别 、用户级别 、系统级别,通常限制每秒调用量。
还有根据是普通用户还是会员,限制调用量,如普通试用版用户,调用量限制每天20次,会员则每天1000次或者不限制。 还有根据调用次数计费的模式,这应该不属于流控的范畴了,属于业务模式。
上面讲了流控,但流控的阈值并不是拍脑门就定下来的,而是经过实际的线上环境的压测得出的。当前线上服务能支撑多大并发,峰值是多少,都要提前进行评估。要不然你写个1000QPS结果你的服务根本达不到,那不是坑人的吗?接入方以为你们闹着玩呢,瞎写。
另外,还要在接入方接入之前,充分了解接入方的流量,因为你们提供的QPS阈值,可能是针对所有接入方一起限制的。结果来了一个浏览很大的接入方,比如12306,那不就把你们系统搞挂了吗,而且接入方还会觉得你们系统不行,三天两头搞挂了,还会跟你们合作嘛。
所以压测是很必要的,针对接入方的流量,考虑是否能支撑,是否需要加配置加机器等等。
即使使用https接口,有一些行业(例如,银行,金融,军事,政府之类的)还是希望能用自己的方式对数据(特别是敏感数据)加密。
加密分为对称加密和非对称加密,对称加密简单理解就是加密的密文可以通过一定的手段解密,非对称加密就是加密的密文无法解密。
api开放平台作为对外开放的大门,很多东西需要统一。
例如,异常码,数据参数名称,接口名称。api平台作为业务系统一般不保存业务数据,即数据源来自于底层的各种服务,如商品服务,订单服务,库存服务等,api平台对外开放的接口往往需要通过调用多个服务的接口,但是,多个服务之间的开发规范可能不一样,定义的异常码,参数名等不尽相同。
因此api平台需要对外统一口径,对各个服务返回的异常码,参数名进行包装。如商品服务定义的参数错误异常码为100203,订单服务定的参数错误的异常码为200100,如果api平台仅做透传,不对数据处理,那么对外的表现就是一种异常对应两个异常码,显得不专业。
以上考虑的并不是非常全面,目前想到的就这些,以后还会补充完善。