iopiop

Рейтинг
25
Регистрация
23.12.2010

deleted......

я не понимаю как может срабатывать ваша проверка т.к. я не вижу где устанавливается нулевой элемент массива $protect

---------- Добавлено в 03:33 ---------- Предыдущее сообщение было в 03:17 ----------

goodier:

В любом случае когда каждую следующую минуту крон будет обращаться к нашему новому файлу,
будет происходить проверка по колонке state=0 и в условии будет сравнивать текущий с
предыдущим значением из массива, просто я другого решения не нашел и стал использовать массив.

заметьте, эта заявка все равно будет обработана, хотя пользователь заблокирован

if($protect[$k] == $protect[$k-1])

что будет если селект вернет только одну запись?

у вас получается нельзя пользоваться вашим сервисом чаще чем раз в сутки на одинаковую сумму?

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

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

siv1987:
Можно просто формировать заявку и выдать кнопку бабло которая запустит независимый скрипт обработке заявки.

боюсь что хацкеру плевать на формочки-кнопочки, он напрямую в скрипт долбится. чтобы ваш вариант работал надо продумывать схему с рандомным числом каким-нибудь для этой кнопочки и проверять потом его. хрень редьки не слаще.

goodier:
То есть если один раз сработает команда flock( $fp, LOCK_EX ) ,
то повторно она уже не сработает пока не произойдет flock($fp, LOCK_UN)
да или нет, вот этот момент у меня в голове не укладывается.

да

используйте функцию GET-LOCK из MySQL вместо флок, это намного проще. в качестве имени лока используйте логин пользователя.

вначале своего скрипта дергаете эту функцию и все. если кто-то уже положил лок и держит его, то ваш вызов будет просто тупо ждать пока лок не освободится, никаких if не надо.

на выходе из скрипта делайте RELEASE_LOCK

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

конечно, это даже распараллелит процесс. при условии что ваша pay функция не пишет в какие-нибудь общие для всех пользователей переменные.

вот здесь почитайте http://stackoverflow.com/questions/2921469/php-mutual-exclusion-mutex

goodier:
iopiop Этот человек и до того как я добавил SLEEP() умудрялся снимать двойную сумму

sleep() - это только один из многих операторов который приводит к такому эффекту. напр. любой оператор IO тоже обладает таким же свойством. более того, sleep и иже с ним только резко повышают такой ход событий, на самом деле и без них такое может случится. выполнение вашего кода может быть прервано в абсолютно любой точке программы и вы на это влиять не можете. это называется "вытесняющая многозадачность".

та проблема о которой я написал лечится созданием флага, который говорит "сейчас этот скрипт занят, ждите". флагом может быть напр. просто файл. алгоритм

1. проверить, есть ли файл lock

2. если есть - спать 2-3 секунды, и идти к п.1

3. если нет - создать

4. после этого вся ваша функция

5. в конце функции удалять файл lock

о чем нужно беспокоится

а) у вас много exit() - соответственно нужно переделать, чтобы эти exit() удаляли файл lock перед выходом

б) возможна ситуация когда компьютер сбойнет в то время когда этот файл существует, это приведет к бесконечному циклу при старте. это значит что перед запуском вашего приложения нужно убедиться что такого файла нет, если есть - удалить ручками. собственно, любая ошибка которая может случится в этой функции должна не просто прекращать работу функции, а удалять этот файл.

возможно, кто-нибудь, кто знает MySQL лучше меня, расскажет как такое же можно сделать используя БД, а не файл. скорее всего это будет более правильным решением, особенно если использовать транзакции и внутри них лочить таблицы.

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

goodier:

Первый запрос проходит проверку if($summa > balance($login)) и это условие не срабатывает так как баланс еще тот же и сразу после проверки в условии с баланса снимается сумма.
Второй запрос уже не должен пройти так как условии должно сработать ведь в функции проверяется баланс а не где то выше условия из БД.

читайте внимательно что вам пишут. повторю - выполняется первый запрос включая проверку if($summa > balance($login)). В этот момент, до снятия с баланса, приходит второй запрос. выполнение первого запроса может прерваться и процессор пойдет выполнять второй запрос. и может полностью отработать второй запрос и после этого вернуться продолжать выполнять первый запрос. деньги сняты вторым запросом, проверка в первом запросе уже пройдена. вероятность такого поведения сильно повышается если у вас в коде используются некоторые операторы, один из которых sleep.

добро пожаловать в многозадачные операционные системы.

именно поэтому я и говорю - нужен весь код если вы хотите чтобы вам нашли ошибку. то, что вы делаетет какие-то проверки, это не видно совершенно. более того, в первом посте вы сумму брали напрямую из $_POST . мы должны догадаться что там уже что-то проверено? гадать как-то надоедает. нет кода - я умываю руки, я не телепат.

goodier:
RoMaN444Ik,
Мой код который я привел в примере обрезан.

как вы хотите чтобы вам нашли баги, если код обрезан??? 😮

goodier:

В нем нет функций sleep(2) и mysql_escape_string($_post[blablabla])

а ведь это очень важно, дьявол в деталях

goodier:

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

я вам уже предложил подумать, что будет если у вас есть пользователи vasya1, vasya2, vasya3 и vas%. Что вернет проверка баланса с вашим любимым like для пользователя vas% ? для какого реально пользователя будет возвращен баланс? я вот не знаю. и скажу вам по секрету, никто не знает.

это один вариант развития событий.

другой вариант - что происходит если сумма передается в этот код отрицательная? я не знаю, т.к. код не полный.

третий вариант событий. предположим пришел запрос, начинает выполняться, прошел проверку if($summa > balance($login)) и в этот момент приходит второй запрос. первый запрос перестает выполняться, выполняется второй запрос, выполнился полностью и процессор вернулся к выполнению первого запроса. заметьте, проверка баланса в первом запросе уже прошла, и прошла удачно, о том что деньги сняты вторым запросом, первый запрос ничего не знает. кстати именно во время sleep и происходит переключение контекста.

1. выложите весь код, если хотите получить советы по коду

2. записывайте в файл все что приходит на вход этой функции, чтобы видеть, не подставляются ли левые данные типа отрицательной суммы.

3. отдайте эту часть сделать профессионалу, дешевле будет.

баян, но уж больно в тему

LEOnidUKG:
Не верно, надо
if($balance <= 0){ exit("Недостаточно средств!"); }

эта строчка вообще лишняя, буквально в следующей опять та же проверка идет

Всего: 259