Обнаружение при необходимости капчи


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

В истории таблица нужна только для отображения капчи. Двигатель=InnoDB является выбранный в таблице истории.

Без индексов были введены на время или имя пользователя или 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


253
2
задан 5 декабря 2011 в 10:12 Источник Поделиться
Комментарии
2 ответа

1, Вы должны создать эти индексы. Объяснять показывает ли ваши запросы, использовать индексы или нет. Если у вас пока нет, может быть, вы хотите хрон, который регулярно удаляет старые записи из таблицы. Это тоже повышает производительность.

2, как по другим вопросам, если это возможно, использовать ПДО , чтобы избежать возможных для SQL инъекций.

3, Выбирайте осмысленные имена вместо $запроса query1 и $query2 (может быть, $remoteAddrQuery и $userIdQuery). Это улучшает читабельность кода. То же верно для $результат1 и $результат2 ($remoteAddrResults, $userIdResults).

4, может быть, одного запроса будет достаточно:

$attemptsQuery = "SELECT id FROM history 
WHERE (Time > date_sub(now(), interval 5 minute))
AND (remote_addr='" . ip2long($_SERVER['REMOTE_ADDR']) . "'
OR userid='" . $userid . "')
LIMIT 6";

5, Если вы не используете в записях просто фото из них граф(*):

$attemptsQuery = "SELECT COUNT(*) as attempts FROM history 
WHERE (Time > date_sub(now(), interval 5 minute))
...
LIMIT 6";

Его результаты немного меньше сетевого трафика между веб-сервером и сервером базы данных и, возможно, означает меньшую нагрузку на базу данных.
Конечно, вы должны изменить mysql_num_rows тоже.

6, Некоторые комментарии излишне:

//so we know mysql_num_rows($result2)

7, а не комментируя создать функции, имена которых говорят, что замечания сказал. Я бы изменила

$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);
}

для

function getMaxAttempts($result1, $result2) {
$attempts = 0;
if ($result1) {
$attempts = max($attempts, mysql_num_rows($result1));
}
if ($result2) {
$attempts = max($attempts, mysql_num_rows($result2));
}
return $attempts;
}

Это делает код более читаемым.

Обратите внимание, что я удалил первый звонок mysql_num_rows($результат2) , который, возможно, повышает производительность немного. (Наверное на PHP кэширует его.) Функции vararg будет лучше с петлей, но я не знаю PHP поддерживает он или нет.

8, Если есть ошибка с запросами или с сервером базы данных mysql_query возвращает значение false. Поэтому не будет капча отображается на всех:

if ($result1) {
$attempts = mysql_num_rows($result1);
}

Может быть, вы хотите войти и/или показать сообщение об ошибке в этих случаях.

4
ответ дан 6 декабря 2011 в 04:12 Источник Поделиться

Это зависит от того, где $userId, которое исходит от. Если его прям из запроса, то да, ваш код уязвим к SQL-инъекции. Поиск в интернете для "Бобби таблицу дропа", чтобы узнать больше.

0
ответ дан 13 апреля 2012 в 02:04 Источник Поделиться