重放攻击与幂等性------从最近被重复扣款26元说起

       本周二, 去外面吃了个饭, 扫码点餐,微信支付, 成功付款26元, 但页面提示失败, 且提示让我稍等, 不要尝试继续支付。 等了一会儿,没有结果。 店里人很多, 没来得问是什么情况, 就再次支付了, 第二次成功。当我查看微信支付记录的时候, 发现扣款两次了。 1分钟后, 另外一个吃饭的人, 也反馈了这个问题, 我们找老板反馈, 老板同意退钱, 甚好。 其实, 这种重复扣款的问题, 是有解决方案的。本文来说说与此相关的一些问题。

       先说说重放, 顾名思义, 就是对客户端发的网络请求包进行replay操作, 如果不采取措施, 肯定会导致服务端的重复动作, 这就是重放攻击。重放攻击的特点是, 两个请求完全一致, 所以, 从直观上来看, 要抵抗重放攻击, 服务端进行除重就可以了。比如,每次请求,客户端随机生成一个random值,放在参数中。如果是重放攻击, 那么这个random值就重复了, 服务端判定为重复包。通常的做法还会在参数中增加当前时间戳,并hmac签名生成token(sign)防篡改, 服务端会校验token(sign)和时间差。

       其实, 计算机中的很多原理,都是一个套路, 来源于生活逻辑, 很多都是合情合理的推理。

       再说说幂等性, 查了不少资料, 发现这个定义其实很模糊, 简单来说, 就是, 客户端(或者用户)发起一次或者多次相同操作,不会产生副作用。有点抽象, 没关系, 还是以类似的上述情形为例:客户端给服务端发送扣款请求, 如果服务端扣款成功, 但是在给客户端返回成功的结果时失败了, 此时, 客户端看到了失败, 以为是服务端没有扣款, 于是客户端重试, 悲剧就发生了------重复扣款。

        这种接口,是没有幂等性的, 无法防止重试,客户端和服务端都忧心忡忡。 一个简单的解决办法就是, 客户端携带随机数, 自动重试时,随机数相同,服务端要判断这个随机数对应的请求在之前是否被处理成功, 避免重复扣款。另一个类似的思路是, 客户端每次都去服务端拉一个随机数(可以理解为服务端分配的订单号), 然后服务端就可以判断了。 随机数在客户端还是在服务端,道理一个样。 此时, 接口就有了幂等性。 

       回到我碰到的那个问题, 很简单, 客户端把订单号带上就可以了, 同一订单,服务端可以防止重复扣款。

       26元算是讨回来了。

       不多说。

猜你喜欢

转载自blog.csdn.net/stpeace/article/details/81154437