Как кто-то сказал ранее, ключ здесь заключается в том, по какой причине вы хотите хранить ips пользователя.
Я приведу пример из системы регистрации, над которой я работаю, и, конечно, решение только для того, чтобы внести свой вклад в это старое обсуждение, которое часто встречается в моих поисках.
Многие регистрационные библиотеки php используют ip для ограничения / блокировки неудачных попыток на основе ip пользователя.
Рассмотрим эту таблицу:
-- mysql
DROP TABLE IF EXISTS `attempts`;
CREATE TABLE `attempts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(39) NOT NULL, /*<<=====*/
`expiredate` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- sqlite
...
Затем, когда пользователь пытается выполнить вход или что-либо, связанное с обслуживанием, например сброс пароля, при запуске вызывается функция:
public function isBlocked() {
/*
* used one of the above methods to capture user's ip!!!
*/
$ip = $this->ip;
// delete attempts from this ip with 'expiredate' in the past
$this->deleteAttempts($ip, false);
$query = $this->dbh->prepare("SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ?");
$query->execute(array($ip));
$attempts = $query->fetchColumn();
if ($attempts < intval($this->token->get('attempts_before_verify'))) {
return "allow";
}
if ($attempts < intval($this->token->get('attempts_before_ban'))) {
return "captcha";
}
return "block";
}
Скажем, например, $this->token->get('attempts_before_ban') === 10
и 2 пользователя приходят с теми же ips, что и в предыдущих кодах , где заголовки могут быть подделаны , затем после 5 попыток каждая забанит оба !
Хуже того, если все они приходят с одного и того же прокси-сервера, в него будут зарегистрированы только первые 10 пользователей, а все остальные будут забанены!
Критическим здесь является то, что нам нужен уникальный индекс для таблицы attempts
, и мы можем получить его из такой комбинации, как:
`ip` varchar(39) NOT NULL,
`jwt_load varchar(100) NOT NULL
, где jwt_load
взято из файла cookie http, следующего за технологией json web , где мы храним только полезную нагрузку зашифрованную , которая должна содержать произвольный / уникальное значение для каждого пользователя.
Конечно, запрос должен быть изменен на: "SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ? AND jwt_load = ?"
, и класс также должен инициировать private $jwt
.