MySQL & Socket.IO - База данных затопления> Дублирование транзакций - PullRequest
0 голосов
/ 17 декабря 2018

Я не знаю точно, где я должен опубликовать мою проблему и вопрос, стоящий за ней, но я попробую здесь.

Некоторое время назад у меня был небольшой проект, где пользователи моглипотратил монеты на раздумья.Эти монеты были сохранены в виде баланса на их учетной записи в моей базе данных MySQL.Интерфейс был подключен к бэкэнду с помощью socket.io, а приложение узла связывалось с базой данных с помощью обычного модуля mysql.

Проблема: К сожалениюЧерез некоторое время я обнаружил, что можно залить / спамить приложение узла, используя соединение socket.io (или открыть веб-сайт несколько раз, чтобы получить тот же результат), чтобы замедлитьMySQL Querys.Вот почему было возможно потратить монеты, которые пользователь имел дважды или более.

Обычный рабочий процесс был таким:

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-адресами?

Если я когда-нибудь найду решение этой проблемы, я смогу запустить проект снова.

1 Ответ

0 голосов
/ 17 декабря 2018

Одним из решений является использование 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.

...