Как пресечь попытки входа в систему - PHP & MySQL & CodeIgniter - PullRequest
7 голосов
/ 18 февраля 2011

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

Должен ли я использовать MySQL?(читай, что это может напрягать БД)Должен ли я управлять газом на пользователя и для всей системы или только для всей системы?(чтобы не дать нормальным людям угадать пароли)Как мне рассчитать мой порог?(поэтому он автоматически адаптируется к изменениям / росту)Как мне получить этот порог?Запросить / рассчитать при каждом сбое или сохранить в кеше?Что я должен использовать для газа?(прочитайте ответ о том, что sleep () может привести к нагрузке на сервер)

У кого-нибудь есть пример кода?

Я новичок в этом, поэтому я ценю помощь!Спасибо

Ответы [ 3 ]

6 голосов
/ 18 февраля 2011

Я реализовал механизм регулирования бедного человека в функции , используя только APC, вот как я его использую:

// allow 60 requests every 30 seconds
// each request counts as 1 (expensive operations can use higher values)
// keep track of IPs by REMOTE_ADDR (ignore others)

$throttle = ph()->Throttle($ttl = 30, $exit = 60, $count = 1, $proxy = false);

if ($throttle === true)
{
    // IP exceded 30 requests in the last 60 seconds, die() here
}

else
{
    // $throttle is a float
    // number of requests in the last 30 seconds / 30 seconds

    /*
     1 req / 30 = 0,033 sec
     5 req / 30 = 0,166 sec
    10 req / 30 = 0,333 sec
    15 req / 30 = 0,5   sec
    20 req / 30 = 0,666 sec
    25 req / 30 = 0,833 sec
    30 req / 30 = 1     sec
    */

    usleep(intval(floatval($throttle) * 1000000));
}

Я использую это на своем Front-Controller и передаю значение моему методу маршрутизации, но это другая история.

Суть в том, что если вы используете APC, вы можете очень быстро хранить данные в памяти и с небольшим потреблением памяти, потому что APC следует методологии FILO. Если вам нужны более длительные тайм-ауты, вы можете использовать что-то, не основанное на памяти.

Кстати: MySQL поддерживает таблицы с механизмом MEMORY.


Проблема с sleep():

Типичный веб-сервер Apache с установленным PHP-модулем в качестве модуля будет потреблять около 10 МБ ОЗУ на экземпляр, чтобы избежать превышения доступного объема памяти, есть некоторые параметры Apache, которые можно настроить, чтобы ограничить максимальное количество экземпляров, которые может использовать Apache. для начала.

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

Нет способа преодолеть это с помощью PHP AFAIK, так что, в конце концов, решать вам.


Принцип одинаков для дросселирования всей системы:

function systemWide($ttl = 86400, $exit = 360)
{
    if (extension_loaded('apc') === true)
    {
        $key = array(__FUNCTION__);

        if (apc_exists(__FUNCTION__) !== true)
        {
            apc_store(__FUNCTION__, 0, $ttl);
        }

        $result = apc_inc(__FUNCTION__, 1);

        if ($result < $exit)
        {
            return ($result / $ttl);
        }

        return true;
    }

    return false;
}
1 голос
/ 18 февраля 2011

Журнал неудачных попыток входа в систему в таблице, подобной этой:

FailedLogins
id
timestamp
ip

Каждый раз, когда пользователь пытается войти, вы проверяете, есть ли у IP-адреса пользователя число неудачных попыток входа в систему за последние Y секунд.

Если пользователь потерпел неудачу X раз в течение Y секунд, вы выводите сообщение об ошибке или CAPTCHA.

0 голосов
/ 18 февраля 2011

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

Вы также можете использовать сон () ПРИМЕЧАНИЕ: PHP обрабатывает больше пользователей, чем ASP.NET - и снова. Если у вас нет тысяч пользователей, вы можете использовать методы сна без узких мест.

Я обычно делаю это, сохраняя попытки входа (IP, userID и timestamp). Храните его в таблице и сбрасывайте таблицу, когда вам это нравится (при определенном размере или времени суток). Если идентификатор пользователя + IP превышает «количество попыток входа в систему» ​​за «определенное время», перенаправьте пользователя на страницу, которая сообщает пользователю о том, что он / она использовал много попыток и не сможет войти следующие 15 минут (или как вы чувствуете). Немного "Windows", как я думаю, но это работает как шарм:)

...