5

后端接口对接注意事项 - 王李峰

 2 years ago
source link: https://www.cnblogs.com/wanglifeng717/p/16213202.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

后端接口对接注意事项

后端接口对接的模式范本:

概念澄清:

【下单】是个广义上的叫法,并不仅限于支付订单的订单。因为整个过程都围绕一个【seqNo】订单号或流水号这个唯一标识展开,因而统称【下单】。

【下单】可以是为派发一个优惠券、申请一个支付订单、申请一个发票等等。

【seqNo】也可以叫orderNo,有唯一性,每次请求都不一样,唯一标识一笔业务。

后端接口需要考虑的点:   

  • 通信层安全验证(可以通过nginx层做https的证书验证工作)
  • 单向https.

即客户端验证服务端证书。例如:浏览器验证网站证书。

我们需要做的就是服务端的证书一定是要第三方授信CA签的证书。

这样浏览器拿到证书可以在本地找到该授信的第三方ca证书来验证网站证书的真伪。

如果网站的证书自己签名的证书,客户端需要在浏览器中配置该证书自签名使用的的CA证书。

https单向相比于双向实现方便,也是最基础的保障。不可能http直接在公网上跑,那样业务报文都是明文暴露状态,非常不安全。

  • 双向https

一般后端交互https双向,基本都是使用自签名的证书。

客户端需要配置服务端的ca证书,用于解开服务端给我们的其自身的证书。

服务端同时也需要配置客户端的ca证书,用于解开客户端给服务端的其自身的证书。

如果是代码实现发送双向https请求,你会发现有两个证书配置,一个是请求方自身的证书,一个是服务端的ca证书。

https双向优点就是更加安全,通过证书能互相确认彼此身份。在后端交互中常见。单向https在浏览器/服务端中常见。

  • 接口层校验:

接口或者header中有类似于sign的字段,用于验证签名。

签名的作用就两个:防篡改;防抵赖

sign = sha256WithRSA(报文,私钥)等方法的模式为【私钥签名、公钥验签】的方式,可以防篡改,防抵赖.但是实现相对较重,需要生成和管理公私钥。

使用appkey/secretKey模式,使用类似于sign=MD5(报文,secretkey)只能防篡改,因为这个secretKey是双方都知道的.但是实现方式较轻量,也很普遍。

  • 数据安全保护

通信层https只能保证数据在网络或者公网中是密文传输的。

但是一旦数据过了nginx这关,即解除https证书验证之后,报文数据在内网中就是明文在传输。对应敏感数据不能明文显示。

复杂安全点的模式可以使用数字信封模式:

即提供两个字段:

partnerData:敏感数据的加密值,使用对称加密的,例如:AES算法。

dekey:随机对称密钥的加密值,使用非对称加密的,例如:RSA算法

partnerData=AES(敏感数据,随机对称密钥)  

dekey=RSA(随机对称密钥,接收方的公钥)

解密的过程就是加密的逆过程,先用自己的私钥解出对称密钥,再使用对称密钥解开敏感数据。

因为基于公私钥,所以只有私钥持有者才能解开这个数字信封。安全性非常好。

  • 业务授权校验:

通信层可以进来,验签能通过。但是业务授权也要鉴别,例如:同样可以调用派发优惠券接口,但是商户A只能发商户A商品的优惠券。

接口或者header中有类似于appkey/appCode/authCode等类似功能字段,该字段和验签绑定。通过该字段查询配置,确认该请求是否有该业务的权限。

  • 防重发攻击:

https单向中多见,https双向中少见。主要预防攻击不要流到业务层。

1.防止错误的报文重复攻击,一般错误报文验签直接可以过滤。

2.防止正确的报文重复攻击

一般在接口或者header中有timestamp/nonce/messageId等字段,这些字段每次请求都会不一致。

如果报文被截获,重放攻击,可能由于timestamp时间和服务器时间相差很远,或者相关nonce字段已经被缓存过,无法通过。

同时可以结合幂等措施,即被处理过的业务不会重复执行。

  • 实现幂等:

接口中有seqNo字段,可以叫订单号/流水号。

一个seqNo就对应了一次业务下单,同样的流水号无论请求多少次,结果都是一样的,不会重复做。

防止请求在通信中丢失,请求方无法判断该业务的实际状态,是【还未送达】或【处理完了,回程时丢失】

实现幂等后,请求方可以使用相同seqNo进行下单,服务端如果处理过该seqNo订单,就将之前的处理结果返回,如果没处理就收单继续处理。

为什么提供了幂等还要提供查询?

查询和幂等的作用区别就在于,很多时候请求方请求出现异常,没有明确的答案,如果希望业务继续,则可以幂等请求。

例如该用户派发优惠券,如果发生异常则继续幂等派发即可。

如果需要根据实际业务状态决定如何操作,则需要先查询。

例如:很多有时效的业务,抢购业务,用户下单异常,最终没抢到货。

肯定是先查询,如果刚才订单实际成功,则给用户退款。如果刚才订单未成功,则直接关闭业务,这单子不用继续做下去了。

  • 异步通知:

下单接口如果是同步接口,肯定没有实现异步通知的必要。

很多下单接口是异步接口,真正的业务状态在同步中无法返回,同步仅仅返回已收单。

异步通知的作用:能增强业务的时效性,同时也能减少请求方轮询导致的压力。

如果收到明确通知,请求方当即可以触发下一步操作,如果没有通知或通知丢失,请求方只能挂单等待异常处理时主动查询确认状态。

  • 是否需要对账

一般后端对接的业务接口,基本都需要对账。

对账最大的问题是【跨天】,例如:请求方请求时间为凌晨:23:59:59.但是接收方收到的时间为次日:00:00:04

假如按照T+1对账,那在T日临界点,总可能出现对不平的情况。请求方有该笔账,但是接收方没有。

我们不讨论【勾对】等其他实现方式。

如果可能,在定义接口的时候,可以讨论清楚对账方式及以哪方时间为准。避免后续对账开发困难。

例如:在下单接口中添加objectData字段,以请求方的该字段作为对账时间依据。

对接的任何一方都有在业务进行中要升级接口的可能。但是要避免需要停服、及互相依赖的局面,例如:大家约定一个时间,半夜你先升级,我在升级。

场景1:公私钥泄露需要更换。

可以在接口中添加keyIndex来标识密钥的版本或者signType字段来标识签名的算法。

这样请求方报文中使用什么版本的密钥,接收方就使用什么版本的密钥解密。互相不依赖。提前配置好即可。

场景2:接口字段升级

下单接口有新增字段,选择升级接口版本号,形成一个新接口。老接口仍保留。接收方先升级,请求方择机升级,互不影响。

查询同理。

网络异常、网络波动、今天我灾备、明天他机房维护等。这些单个事件都是小概率,但是这样的事件非常多。

网络异常也导致很多业务异常,我们要充分考虑的异常导致的挂单和中断的情况,做好异常处理和自愈功能。

例如:对账往ftp上投送对账文件。可能网络异常,今天的文件没放上去;或者今天的放上去了,但是出问题需要重新放;可能灾备停了两天,在进行对账等等

ps:不要忽略这些小概率事件,没有预案,只要发生一次,造成的异常业务笔数可能手动处理很久。

考虑这个接口的负载是很关键的步骤。同步接口压力大点,异步接口可以使用MQ进行削峰填谷相对压力小点。

提升效率,控制并发是一个非常庞大的体系。常见的方式:
1.共享数值字段,我们只做累加

2.每个用户独立有一条记录,将并发化解。

4.用插入代替更新,分段锁库存等,使用<=0代替=0,防止极限情况击穿等。

5.分库分表,避免热点表和数据的阻塞。

6.注意风控,报警等情况。

...............

{
"authCode": "123", 业务认证码
"appCode": "123", 请求方
"deKey":"frfferdfa" 对称密钥加密值
"partnerData": "22", 敏感数据加密值
"seqNo": "123",请求流水
"timestamp": "202107201653123", 时戳
"keyIndex": "1", 加密密钥版本
"sign": "123" 签名
}

 本文来自博客园,作者:wanglifeng,转载请注明原文链接:https://www.cnblogs.com/wanglifeng717/p/16213202.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK