我不知道我应该在哪里发布我的问题及其背后的问题,但我会在这里尝试一下。
前段时间我有一个小项目,用户可以在思考上花钱。这些硬币作为余额存储在我的MySQL数据库中的用户帐户上。前端使用socket.io
连接到后端,节点应用程序使用常规mysql
模块与数据库通信。
问题:不幸的是,过了一段时间后我发现有可能使用socket.io连接(或多次打开网站以获得相同的结果)来泛滥/垃圾邮件节点应用程序,以减慢mysql查询速度。这就是为什么用户可以花两倍或更多钱的原因。
正常的工作流程如下:
Request to DB
check balance
if balance > 0
spend coins
reduce coins in DB
else
reject
请求结束
如何花两次硬币:(问题)
Request to DB
Request to DB
check balance
check balance
if balance > 0
if balance > 0
spend coins
spend coins
reduce coins in DB
reduce coins in DB
else
reject
Request end
Request end
由此可以在更新余额之前达到代码以花费硬币。
问题:如何阻止用户做这些事情?使用请求限制器仅适用于使用相同IP的人,因此scriptkiddys不应该能够达到我上面提到的内容。那些使用不同ip的小型僵尸网络的人呢?
如果我得到解决该问题的解决方案,我可以再次启动该项目。
一种解决方案是使用select for update ... where user = XXX
锁定check balance
。
另一种解决方案是添加version
色谱柱。然后get balance and version
,(让我们假设verison是n),spend
,reduce coins and set version= n+1 where version == n
,然后填补失败。在这个解决方案中,你应该在spend coins
后reduce succeeded.
。
这些只是一般的解决方案,仅作为参考,因为我不熟悉socket.io。