我不确定应该在哪里发布我的问题以及它背后的问题,但是我会在这里尝试一下。
前一段时间,我有一个小项目,用户可以在思考上花钱。这些硬币作为余额存储在我的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的用户,因此脚本不足应该无法达到我上面提到的目标。人们使用带有不同IP的小型僵尸网络怎么办?
如果我有解决该问题的方法,则可以再次启动该项目。
答案 0 :(得分:1)
一种解决方案是使用select for update ... where user = XXX
锁定check balance
。
另一种解决方案是添加一个version
列。然后get balance and version
,(假设顶点为n),spend
,reduce coins and set version= n+1 where version == n
,则后面的填充失败。在此解决方案中,您应该在spend coins
之后reduce succeeded.
。
这些只是一般的解决方案,仅供参考,因为我对socket.io不熟悉。