Ограничение отправки сообщений по IP

отправка сообщений по ip

От автора: идея этого урока взята из комментариев пользователей сайта webformyself.com. В комментариях к уроку «Как определить IP адрес пользователя» был задан вопрос возможно ли ограничивать отправку сообщений из формы обратной связи по IP пользователя. Сделать это совсем не сложно, и в этом уроке я покажу один из вариантов реализации этой задачи.

План урока:

    1. Постановка задач (10:08)

    2. Получаем IP из файла (11:54)

    3. Сравниваем полученный IP с IP из файла (9:02)

    4. Отправляем сообщение (20:44)

скачать исходникискачать урок

1. Постановка задач

Прежде всего, давайте определимся, что нам понадобится для успешной реализации поставленной задачи… конечно же, написание любой программы желательно начинать с создания простейшего алгоритма — это значительно облегчает всю дальнейшую работу. Итак, каков будет алгоритм? Поскольку мы будем ограничивать действия пользователя по IP — у нас должна быть некая база IP-адресов, которая будет своеобразным «черным списком» айпишников. После того, как мы получим IP пользователя, обратившегося к скрипту, мы должны будем проверить, есть ли совпадения полученного IP с теми, что есть в нашей БД. Если совпадение будет найдено — мы не будем формировать сообщение, поскольку полученный IP есть в «черном списке». Если же совпадений не будет — мы спокойно будем выполнять нашу программу дальше, т.е. формировать письмо с данными из формы. Вот и весь алгоритм.

Теперь нам понадобится простейшая форма:

<form method="post" action="">
	<table>
		<tr>
			<td>Имя:</td>
			<td><input type="text" name="name" /></td>
		</tr>
		<tr>
			<td>Сообщение:</td>
			<td><textarea cols="40" rows="5" name="mes"></textarea></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" name="submit" value="Отправить" /></td>
		</tr>
	</table>
</form>

Это обычный HTML, а потому объяснять особо здесь нечего. Мы имеем форму с текстовым полем, текстовой областью и кнопкой для отправки данных. Данные будут отправлены методом POST. Атрибут action мы оставим пустым, поскольку данные из формы мы будем принимать на этой же странице. В принципе, о формах мы с Вами уже неоднократно говорили в предыдущих уроках.

Также нам понадобится хранилище IP, для которых мы будем запрещать формирование сообщений, т.е. нам понадобится БД. В качестве такого хранилища мы будем использовать обычный текстовый файл, в каждой строке которого будет находиться один IP-адрес. Файл назовем ip.txt и поместим в него несколько айпишников — я размещу 3 (напоминаю, что 1 IP — 1 строка):

127.0.0.1
127.0.0.2
84.59.100.5

Отлично!

Теперь нам необходимо определить IP пользователя, обратившегося к скрипту. Сделать это можно, обратившись к глобальному массиву $_SERVER — это Вы уже должны знать. После этого мы должны запомнить этот IP или передать его в наш обработчик вместе с данными из формы. Здесь мы используем сессии. Поместив IP в сессионную переменную — мы будем всегда иметь его под рукой на протяжении всего сеанса сессии. Итак, перед формой откроем конструкцию PHP и опишем в коде эти действия:

session_start();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

Напоминаю, что если Вы тестируете скрипт на локальной машине, то IP всегда будет 127.0.0.1

2. Получаем IP из файла

Часть работы мы уже сделали. Теперь необходимо получить данные из файла ip.txt, т.е. наши «черные» айпишники. Сделать это нам поможет функция file(). Эта функция читает содержимое файла и помещает это самое содержимое в массив.

Итак, по нажатию кнопки формы мы будем делать все необходимые действия:

if($_POST['submit']){
	$deny = file('ip.txt');
}

Теперь $deny — это массив с тремя IP из файла. Супер! Данные из файла мы получили. Теперь осталось только сравнить имеющиеся у нас IP с тем, под которым к нам попал пользователь. Здесь следует только учесть 1 небольшой нюанс. Поскольку мы получаем данные из текстового файла с определенной нами структурой хранения данных, перед сравнением необходимо будет каждый из наших айпишников обработать функцией trim(), которая удалит все лишние пробелы из начала и конца строки.

3. Сравниваем полученный IP с IP из файла

Для того, чтобы сравнить каждый из IP массива $deny с IP пользователя, нам понадобится цикл, на каждой итерации которого (на каждом шаге) мы сравним значение каждого конкретного элемента массива с искомым IP. Кроме того, нам понадобится некий флаг (индикатор), отвечающий за сигнализирование о том, что совпадение найдено. Как мы можем реализовать этот флаг. А очень просто. Мы создадим переменную, к примеру, $access со значением ноль. В цикле мы будем проверять совпадение. И здесь мы будем делать следующее: если совпадение будет найдено, мы увеличим значение $access на единицу, иначе — значение этой переменной останется неизменным. По итогу выполнения цикла нам достаточно будет проверить значение $access. Если оно останется равным нулю — значит совпадений найдено не было, иначе — совпадение есть.

Все просто…

$access = 0;
	
foreach($deny as $item){
	if(trim($item) == $_SESSION['ip']) $access++;
}

Теперь мы проверим больше ли значение $access, чем ноль. Также в условии мы проверим наличие в $_SESSION['ip'] самого IP. Последнее мы делаем для того, чтобы обезопасить себя от подделки данных из формы:

session_start();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

if($_POST['submit']){
	$deny = file('ip.txt');
	$access = 0;
	
	foreach($deny as $item){
		if(trim($item) == $_SESSION['ip']) $access++;
	}
	
	if($access > 0 OR empty($_SESSION['ip'])){
	
	}else{
	
	}
}

В итоге мы получили условие. Если оно выполнится (вернет ИСТИНУ) — это будет означать, что к нам зашел «черный» IP. Иначе — мы формируем письмо. Для начала опишем действия в случае совпадения IP:

session_start();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

if($_POST['submit']){
	$deny = file('ip.txt');
	$access = 0;
	
	foreach($deny as $item){
		if(trim($item) == $_SESSION['ip']) $access++;
	}
	
	if($access > 0 OR empty($_SESSION['ip'])){
		$_SESSION['res'] = '<p>Запрещена отправка сообщений!</p>';
		header("Location: index.php");
		exit;
	}else{
	
	}
}

Также после формы выведем значение сессионной переменной и сразу же разрегистрируем ее:

<?php
echo $_SESSION['res'];
session_unset();
session_destroy();
?>

Мы уже можем протестировать скрипт. Если Вы на локальном сервере и в БД есть IP 127.0.0.1 — по нажатию кнопки отправить получим сообщение «Запрещена отправка сообщений!». Если же мы уберем IP 127.0.0.1 из БД — сообщение выводиться не будет.

На самом деле, на мой взгляд, лучше не выводить это сообщение для нежелательных IP, а имитировать отправку сообщений, чтобы не вызывать у данной категории пользователей излишнего интереса. Можно выводить сообщение об успешной отправке данных, но на самом деле их не отправлять или, что еще лучше, отправлять все же сообщение, но с соответствующей пометкой.

4. Отправляем сообщение

С отправкой сообщений Вы также должны быть знакомы, поскольку мы проделывали это уже неоднократно. Напоминаю, что формирует сообщение функция mail(), имеющая 3 обязательных параметра:

e-mail получателя;

тема сообщения;

тело сообщения.

Также есть еще один необязательный параметр, который отвечает за заголовки. В нем можно указать кодировку, в которой будет отправлено сообщение. Соответственно, почтовая программа будет знать, в какой кодировке необходимо открывать полученное сообщение. Если кодировку не указывать, то сообщение будет открыто в кодировке почтовой программы по умолчанию.

Итак, весь код будет таким:

<?php
session_start();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

if($_POST['submit']){
	$deny = file('ip.txt');
	$access = 0;
	
	foreach($deny as $item){
		if(trim($item) == $_SESSION['ip']) $access++;
	}
	
	if($access > 0 OR empty($_SESSION['ip'])){
		$to = 'mail@mail.ru';
		$subject = 'Письмо с сайта - IP из черного списка';
		$body = "Имя отправителя: \r\n" .$_POST['name']. "\r\n\r\n";
		$body .= "Текст сообщения: \r\n" .$_POST['mes']. "\r\n\r\n";
		$body .= "IP отправителя: {$_SESSION['ip']}";
		$headers = 'Content-type:text/plain; Charset=windows-1251';
		mail($to, $subject, $body, $headers);
		
		$_SESSION['res'] = '<p>Сообщение отправлено!</p>';
		header("Location: index.php");
		exit;
	}else{
		$to = 'mail@mail.ru';
		$subject = 'Письмо с сайта';
		$body = "Имя отправителя: \r\n" .$_POST['name']. "\r\n\r\n";
		$body .= "Текст сообщения: \r\n" .$_POST['mes']. "\r\n\r\n";
		$body .= "IP отправителя: {$_SESSION['ip']}";
		$headers = 'Content-type:text/plain; Charset=windows-1251';
		
		if(mail($to, $subject, $body, $headers)){
			$_SESSION['res'] = '<p>Сообщение отправлено!</p>';
			header("Location: index.php");
			exit;
		}else{
			$_SESSION['res'] = '<p>Ошибка!</p>';
			header("Location: index.php");
			exit;
		}
	}
}

?>
<form method="post" action="">
	<table>
		<tr>
			<td>Имя:</td>
			<td><input type="text" name="name" /></td>
		</tr>
		<tr>
			<td>Сообщение:</td>
			<td><textarea cols="40" rows="5" name="mes"></textarea></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" name="submit" value="Отправить" /></td>
		</tr>
	</table>
</form>
<?php
echo $_SESSION['res'];
session_unset();
session_destroy();
?>

Заключение

Вот и все. Теперь в случае, если форму заполняет пользователь с «черным» IP, сообщение будет отправлено с соответствующей пометкой в теме сообщения. Таким образом, поставленная нами задача реализована в полной мере и, как видим, ничего сложного здесь нет.

На этом наш урок закончен. Удачи и до новых встреч!

Автор: Кудлай Андрей. Команда webformyself.

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (17)

  1. Сергей

    А есть ли на вашем сайте урок по созданию обратной связи такой же как на вашем сайте. «Я не робот»

  2. CTOKMAH

    Спасибо за уроки.

  3. Михаил

    А если пользователь зашел через анонимайзер, то возможно ли от этого защититься?

    • Андрей Кудлай

      На то они и анонимайзеры, чтобы скрывать IP клиента. В таком случае можно помещать в список IP анонимайзеров.

      • Михаил

        Это надо тогда добавлять их в списки…но их ппц как много…придумать какую нибудь систему..

        • Андрей Кудлай

          Например? Какую систему можно придумать? Мне кажется в отношении анонимайзеров никакой системы быть не может в принципе. Но, если Вы предложите алгоритм — мы попробуем его реализовать.

  4. OlegBon

    Спасибо, за информацию!
    Материал очень интересен. Очень понравилось как подан материал: план + видео + текст с примерами кода. Всё воспринимается очень легко :)

  5. Максим

    есть и динамические ап которые меняются при желании в любой момент,для дополнительной проверки можно еще вставить cookie и если пользователь поменяет ип то проверяем cookie.

    • Андрей Кудлай

      Да, IP не единственный критерий. При создании серьезного приложения используются еще куки, может собираться информация о клиенте (ОС, браузер, разрешение), которая может использоваться для максимально точной идентификации клиента и его блокировки.

  6. олег

    о чём это вы.

  7. Vladimir

    Здравствуйте…!! А можно ли сделать урок, чтобы за каждый клик на твоём сайте начислялись бы деньги…???

  8. Виктор

    Хороший вопрос задал Владимир )))… Если бы вы создали такой скрипт… цены бы Вам не было!!!

    • Андрей Кудлай

      Я, честно говоря, не понял что Владимир имел в виду. Ну и, наверное, не я один не понял ))) Михаил тоже пытался конкретизировать вопрос… Я, например, не понял зачем нужно начислять деньги за клики по страницам моего сайта? Кто согласится платить за то, чтобы кликали по его сайту?

  9. Алина

    Я так понимаю это один из вариантов реализации.
    например, можно определять наличие в массиве не перебором массива (этот способ нагляднее для начинающих), а функцией in_array().
    А чем хуже способ, если встроить IP
    в качестве значения $_SERVER['REMOTE_ADDR'] в скрытый input и потом его также передать методом POST как и остальные данные формы?
    Мне кажется это тоже нормальный способ.

    • Андрей Кудлай

      По первому вопросу — да, можно использовать и вариант с функцией in_array().
      По второму вопросу — передача IP через скрытое поле возможный, но не самый лучший вариант в данном случае. В уроке я говорил о возможности подделки данных формы. Поскольку форма полностью отдается клиенту, то что мешает ему в качестве значения скрытого поля отправить что-угодно? Ничего. А вот в сессию попадает то, что есть на самом деле.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree