Проверяю в любом случае на наличие блокировки и минусового баланса плюс добавил условие в
файл где юзер создает запрос на выплату.
$pay_date = mysql_fetch_row(mysql_query("SELECT `date` FROM `payout` WHERE `login`='$username' ORDER BY `id` DESC LIMIT 1")); if(in_array(time() , $pay_date)){ exit("Повторите запрос еще раз!"); }
Ragnarok: что если, теоретически, в ту же секунду, как создадутся 2 запроса на вывод, деньги закажет ещё один человек и они занесутся в базу в виде - первый дублирующийся запрос - хороший запрос - второй дубль
if($protect[$k] == $protect[$k-1]) уже не сработает так, как задумано
Я тоже думал над этим, всякое может произойти и придумал, что если проверять в массиве совпадения вот так:
if(in_array($protect[$k] , $protect)) Уже сработает
Ragnarok: сделай очередь заявок и обрабатывай по порядку, без таких вот извращений
Вы предлагаете сделать так чтоб пользователь ждал пока я увижу запрос на выплату и сделаю выплату вручную, но это пользователям не нравится да и у меня просто нет на это время.
iopiop: PS подумайте что произойдет если в базе появится запись в момент когда ваш код пройдет эту проверку, но до апдейтов.
В любом случае когда каждую следующую минуту крон будет обращаться к нашему новому файлу, будет происходить проверка по колонке state=0 и в условии будет сравнивать текущий с предыдущим значением из массива, просто я другого решения не нашел и стал использовать массив. Происходит что то типа такого: если("userlogin-1326839241-100" == "userlogin-1326839241-100"){ то заблокировать и состояние у запроса на выплату обработать как отменено } иначе { проверить баланс на отрицательную сумму и если сумма не отрицательная, только потом выплатить реальные деньги. }
Проверял, тестировал вроде работает, но тему закрывать все таки пока не стоит, Нужно дождаться этого хацкера и посмотреть, что получится с его счетом и аккаунтом.
if($protect[$k] == $protect[$k-1])
{
mysql_query("UPDATE `users` SET `block`=2 WHERE `login`='$login'");
mysql_query("UPDATE `pay_out` SET `state`=2 WHERE `id`='$id'");
} else {
mysql_query("UPDATE `pay_out` SET `state`=1 WHERE `id`='$id'");
/* Отправляю данные через CURL на другой сервер для выплаты денег */
}
}
}
exit();
?>
Вручную создал 4 одинаковые записи в таблице с запросами на выплату
и подождал минуту, вроде работает пока правильно, но это работает в том случае если UNIX время одинаковое.
Ниже смотрите скрин из таблицы статистики платежей этого красавчика который меня грабит ))
dkameleon, Многопользовательский вариант - это и есть лочить файл с названием юзера или нет , понять не могу
вот что нашел про flock:
В некоторых операционных системах flock() реализован на уровне процессов. При использовании многопоточных серверных API, таких как ISAPI, вы не можете полагаться на flock() для защиты ваших файлов от дугих PHP-скриптов, которые работают в параллельном потоке на том же сервере!
/*/*/*/*/*/*/
В итоге мне этот вариант не подходит?
Вот набросал такой код и думаю, что он неправильный.
Ведь если хакер пошлет 100 запросов в секунду, то некоторые сработают потому, что
в WHILE проверяется заблокирован ли файл, а он уже в условии блокируется так как я не знаю что возвращает команда flock и мой код начнет выполнятся.
<?php
session_start();
$login = $_SESSION['username'];
$fp = fopen("LOG_POST/".$login.".txt","a");
$try=false; while(!$try){
if( flock( $fp, LOCK_EX )) { /* уже блокирует файл в условии */
$try=true;
} else {
$try=false;
}
}
if($try){
/* мой скрипт обрабатывается */
if($payout > $userbalance){
flock($fp, LOCK_UN);
fclose($fp);
exit("Недостаточно средств!");
}
mysql_query( 'UPDATE table_users SET balance=balance-$payout WHERE login="'. $login.'"' );
Я так понял файл lock может иметь название какое угодно и если я его буду при обращении к обработчику создавать файл с таким же именем как у пользователя, то другие пользователи не пострадают?
Вообще не желательно использовать маленький размер текста, поисковики этого не любят.
Проверяю в любом случае на наличие блокировки и минусового баланса плюс добавил условие в
файл где юзер создает запрос на выплату.
$pay_date = mysql_fetch_row(mysql_query("SELECT `date` FROM `payout` WHERE `login`='$username' ORDER BY `id` DESC LIMIT 1"));
if(in_array(time() , $pay_date)){
exit("Повторите запрос еще раз!");
}
и кто знает, может это условие все бы решило.
что если, теоретически, в ту же секунду, как создадутся 2 запроса на вывод, деньги закажет ещё один человек и они занесутся в базу в виде
- первый дублирующийся запрос
- хороший запрос
- второй дубль
if($protect[$k] == $protect[$k-1]) уже не сработает так, как задумано
Я тоже думал над этим, всякое может произойти и придумал, что если проверять в массиве совпадения вот так:
if(in_array($protect[$k] , $protect)) Уже сработает
сделай очередь заявок и обрабатывай по порядку, без таких вот извращений
Вы предлагаете сделать так чтоб пользователь ждал пока я увижу запрос на выплату и сделаю выплату вручную, но это пользователям не нравится да и у меня просто нет на это время.
PS подумайте что произойдет если в базе появится запись
в момент когда ваш код пройдет эту проверку, но до апдейтов.
В любом случае когда каждую следующую минуту крон будет обращаться к нашему новому файлу,
будет происходить проверка по колонке state=0 и в условии будет сравнивать текущий с
предыдущим значением из массива, просто я другого решения не нашел и стал использовать массив.
Происходит что то типа такого:
если("userlogin-1326839241-100" == "userlogin-1326839241-100"){
то заблокировать и состояние у запроса на выплату обработать как отменено
} иначе {
проверить баланс на отрицательную сумму и если сумма не отрицательная,
только потом выплатить реальные деньги.
}
Проверял, тестировал вроде работает, но тему закрывать все таки пока не стоит,
Нужно дождаться этого хацкера и посмотреть, что получится с его счетом и аккаунтом.
Написал скриптик для крона:
<?php
$path = "/var/www/UserName/data/www/Domain.ru/";
include($path."DB_conf.php");
$query = mysql_query("SELECT * FROM `pay_out` WHERE `state`='0' ORDER BY `id`");
if(mysql_num_rows($query) > 0)
{
$k = 0;
$protect = array('null');
while($res = mysql_fetch_array($query))
{
$k++;
$id = $res['id'];
$login = $res['login'];
$date = $res['date'];
$summa = $res['summa'];
$protect[$k] = $login."-".$date."-".$summa;
if($protect[$k] == $protect[$k-1])
{
mysql_query("UPDATE `users` SET `block`=2 WHERE `login`='$login'");
mysql_query("UPDATE `pay_out` SET `state`=2 WHERE `id`='$id'");
} else {
mysql_query("UPDATE `pay_out` SET `state`=1 WHERE `id`='$id'");
/* Отправляю данные через CURL на другой сервер для выплаты денег */
}
}
}
exit();
?>
Вручную создал 4 одинаковые записи в таблице с запросами на выплату
и подождал минуту, вроде работает пока правильно, но это работает в том случае если UNIX время одинаковое.
Ниже смотрите скрин из таблицы статистики платежей этого красавчика который меня грабит ))
То есть если один раз сработает команда flock( $fp, LOCK_EX ) ,
то повторно она уже не сработает пока не произойдет flock($fp, LOCK_UN)
да или нет, вот этот момент у меня в голове не укладывается.
dkameleon, Многопользовательский вариант - это и есть лочить файл с названием юзера или нет , понять не могу
вот что нашел про flock:
В некоторых операционных системах flock() реализован на уровне процессов. При использовании многопоточных серверных API, таких как ISAPI, вы не можете полагаться на flock() для защиты ваших файлов от дугих PHP-скриптов, которые работают в параллельном потоке на том же сервере!
/*/*/*/*/*/*/
В итоге мне этот вариант не подходит?
Вот набросал такой код и думаю, что он неправильный.
Ведь если хакер пошлет 100 запросов в секунду, то некоторые сработают потому, что
в WHILE проверяется заблокирован ли файл, а он уже в условии блокируется так как я не знаю что возвращает команда flock и мой код начнет выполнятся.
<?php
session_start();
$login = $_SESSION['username'];
$fp = fopen("LOG_POST/".$login.".txt","a");
$try=false; while(!$try){
if( flock( $fp, LOCK_EX )) { /* уже блокирует файл в условии */
$try=true;
} else {
$try=false;
}
}
if($try){
/* мой скрипт обрабатывается */
if($payout > $userbalance){
flock($fp, LOCK_UN);
fclose($fp);
exit("Недостаточно средств!");
}
mysql_query( 'UPDATE table_users SET balance=balance-$payout WHERE login="'. $login.'"' );
flock($fp, LOCK_UN);
fclose($fp);
exit("Деньги выплачены!");
}
?>
betam,
Вот набросал такой код и думаю, что он неправильный.
Ведь если хакер пошлет 100 запросов в секунду, то некоторые сработают потому, что
в WHILE проверятеся заблокирован ли файл, а он уже в условии блокируется и мой код начнет выполнятся.
<?php
session_start();
$login = $_SESSION['username'];
$fp = fopen("LOG_POST/".$login.".txt","a");
$try=false; while(!$try){
if( flock( $fp, LOCK_EX )) { /* уже блокирует файл в условии */
$try=true;
} else {
$try=false;
}
}
if($try){
/* мой скрипт обрабатывается */
if($payout > $userbalance){
flock($fp, LOCK_UN);
fclose($fp);
exit("Недостаточно средств!");
}
mysql_query( 'UPDATE table_users SET balance=balance-$payout WHERE login="'. $login.'"' );
flock($fp, LOCK_UN);
fclose($fp);
exit("Деньги выплачены!");
}
?>
dkameleon, СКАЖИТЕ МНЕ ПОЖАЛУЙСТА ПО РУССКИ
что значит АТОМАРНОСТЬ - это то что предлагает iopiop
создавать файл и с помощью его блокировать возможность обратиться к файлу обработчику? или что это вообще?
Я так понял файл lock может иметь название какое угодно и если я его буду при обращении к обработчику создавать файл с таким же именем как у пользователя, то другие пользователи не пострадают?