Есть ли дыры / возможная оптимизация в этом php-коде, чтобы определить, нужна ли CAPTCHA? - PullRequest
1 голос
/ 06 декабря 2011

Я хочу спросить, есть ли в приведенном ниже коде дыры (возможно, это будет полезно для кого-то еще).Этот код проверяет, было ли выполнено более 5 попыток за последние 5 минут для входа в систему.Проверяется по ip и userid.Каждая попытка входа в систему хранится в таблице истории (MySQL).

таблица истории необходима только для отображения CAPTCHA.ДВИГАТЕЛЬ = InnoDB выбран.(Рекомендуете ли вы использовать MyISAM для повышения производительности? Рекомендуете ли вы указывать индекс для Time или userid или remote_addr?)

Есть предложения по оптимизации?Возможные дыры?Спасибо.

$query1="SELECT id FROM history WHERE (Time>date_sub(now(), interval 5 minute)) AND remote_addr='".ip2long($_SERVER['REMOTE_ADDR'])."' limit 6"; //limit 6 is for performance, 6+ means 6, we only care if it less than 5
$result1=mysql_query($query1);
//so we know mysql_num_rows($result1)


$query2="SELECT id FROM history WHERE (Time>date_sub(now(), interval 5 minute)) AND userid='".$userid."' limit 6";//limit 6 is for performance, 6+ means 6, we only care if it less than 5
$result2=mysql_query($query2);
//so we know mysql_num_rows($result2)



$attempts=0;//we want to set up $attempts=maximum of (mysql_num_rows($result1), mysql_num_rows($result2))
if($result1) {
    $attempts=mysql_num_rows($result1);
}
if($result2 && $attempts<mysql_num_rows($result2)) {
    $attempts=mysql_num_rows($result2);
}

//if $attempts is more than 5, then CAPTCHA should be displayed, if less then it should not

PS Вы все еще рекомендуете использовать usleep (100000) или любой другой метод для предотвращения грубой силы на случай, если кто-нибудь напишет алгоритм однажды (пока капча не станет сильнее), чтобы взломать капчи?

Добавлено: спасибо за вопрос, да, $ userid очищен от плохих символов.

1 Ответ

3 голосов
/ 06 декабря 2011

Нет проблем с безопасностью, если $ userid очищен, но я бы предложил следующие изменения, чтобы сделать код более эффективным: Используйте функцию COUNT MySQL вместо возврата шести идентификационных номеров.Если вам не нужно использовать идентификаторы, не извлекайте их.Кроме того, я не вижу смысла запрашивать базу данных дважды.Уменьшите его немного.

Код ниже короче, быстрее и безопаснее (с mysql_real_escape_string() - я бы рекомендовал взглянуть на эту функцию).Мы исключаем запрос, пару if операторов и экономим на отправке ненужных данных по сети:

$userid = mysql_real_escape_string('...');
$ip = ip2long($_SERVER['REMOTE_ADDR']);

$q = "SELECT COUNT(*) AS cnt FROM history 
  WHERE Time > date_sub(now(), interval 5 minute)
  AND (remote_addr='$ip' OR userid='$userid')
";
$r = mysql_query($q);

// first value, first row (we only get one using count)
$attempts = mysql_result($r, 0, "cnt");

// if $attempts is more than 5, then CAPTCHA should be displayed ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...