От автора: идея этого урока взята из комментариев пользователей сайта 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 есть в «черном списке». Если же совпадений не будет — мы спокойно будем выполнять нашу программу дальше, т.е. формировать письмо с данными из формы. Вот и весь алгоритм.
Теперь нам понадобится простейшая форма:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<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 и опишем в коде эти действия:
1 2 |
session_start(); $_SESSION['ip'] = $_SERVER['REMOTE_ADDR']; |
Напоминаю, что если Вы тестируете скрипт на локальной машине, то IP всегда будет 127.0.0.1
2. Получаем IP из файла
Часть работы мы уже сделали. Теперь необходимо получить данные из файла ip.txt, т.е. наши «черные» айпишники. Сделать это нам поможет функция file(). Эта функция читает содержимое файла и помещает это самое содержимое в массив.
Итак, по нажатию кнопки формы мы будем делать все необходимые действия:
1 2 3 |
if($_POST['submit']){ $deny = file('ip.txt'); } |
Теперь $deny — это массив с тремя IP из файла. Супер! Данные из файла мы получили. Теперь осталось только сравнить имеющиеся у нас IP с тем, под которым к нам попал пользователь. Здесь следует только учесть 1 небольшой нюанс. Поскольку мы получаем данные из текстового файла с определенной нами структурой хранения данных, перед сравнением необходимо будет каждый из наших айпишников обработать функцией trim(), которая удалит все лишние пробелы из начала и конца строки.
3. Сравниваем полученный IP с IP из файла
Для того, чтобы сравнить каждый из IP массива $deny с IP пользователя, нам понадобится цикл, на каждой итерации которого (на каждом шаге) мы сравним значение каждого конкретного элемента массива с искомым IP. Кроме того, нам понадобится некий флаг (индикатор), отвечающий за сигнализирование о том, что совпадение найдено. Как мы можем реализовать этот флаг. А очень просто. Мы создадим переменную, к примеру, $access со значением ноль. В цикле мы будем проверять совпадение. И здесь мы будем делать следующее: если совпадение будет найдено, мы увеличим значение $access на единицу, иначе — значение этой переменной останется неизменным. По итогу выполнения цикла нам достаточно будет проверить значение $access. Если оно останется равным нулю — значит совпадений найдено не было, иначе — совпадение есть.
Все просто…
1 2 3 4 5 |
$access = 0; foreach($deny as $item){ if(trim($item) == $_SESSION['ip']) $access++; } |
Теперь мы проверим больше ли значение $access, чем ноль. Также в условии мы проверим наличие в $_SESSION[‘ip’] самого IP. Последнее мы делаем для того, чтобы обезопасить себя от подделки данных из формы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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{ } } |
Также после формы выведем значение сессионной переменной и сразу же разрегистрируем ее:
1 2 3 4 5 |
<?php echo $_SESSION['res']; session_unset(); session_destroy(); ?> |
Мы уже можем протестировать скрипт. Если Вы на локальном сервере и в БД есть IP 127.0.0.1 — по нажатию кнопки отправить получим сообщение «Запрещена отправка сообщений!». Если же мы уберем IP 127.0.0.1 из БД — сообщение выводиться не будет.
На самом деле, на мой взгляд, лучше не выводить это сообщение для нежелательных IP, а имитировать отправку сообщений, чтобы не вызывать у данной категории пользователей излишнего интереса. Можно выводить сообщение об успешной отправке данных, но на самом деле их не отправлять или, что еще лучше, отправлять все же сообщение, но с соответствующей пометкой.
4. Отправляем сообщение
С отправкой сообщений Вы также должны быть знакомы, поскольку мы проделывали это уже неоднократно. Напоминаю, что формирует сообщение функция mail(), имеющая 3 обязательных параметра:
e-mail получателя;
тема сообщения;
тело сообщения.
Также есть еще один необязательный параметр, который отвечает за заголовки. В нем можно указать кодировку, в которой будет отправлено сообщение. Соответственно, почтовая программа будет знать, в какой кодировке необходимо открывать полученное сообщение. Если кодировку не указывать, то сообщение будет открыто в кодировке почтовой программы по умолчанию.
Итак, весь код будет таким:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<?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.
Комментарии (17)