Обмеження відправки повідомлень по IP

18

Від автора: ідея цього уроку взята з коментарів користувачів сайту webformyself.com. У коментарях до уроку «Як визначити IP-адресу користувача» було задано питання можливо обмежувати відправлення повідомлень з форми зворотного зв’язку по IP користувача. Зробити це зовсім не складно, і в цьому уроці я покажу один з варіантів реалізації цього завдання.

План уроку:

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

2. Отримуємо IP з файлу (11:54)

3. Порівнюємо отриманий IP IP з файлу (9:02)

4. Відправляємо повідомлення (20:44)

Обмеження відправки повідомлень по IPОбмеження відправки повідомлень по IP

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

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

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

Ім’я:
Повідомлення:

Це звичайний 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’] = ‘

Заборонена відправлення повідомлень!

‘;
header(«Location: index.php»);
exit;
}else{
}
}

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

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

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

4. Відправляємо повідомлення

З відправкою повідомлень Ви також повинні бути знайомі, оскільки ми проходили це вже неодноразово. Нагадую, що формує повідомлення функція mail(), що має 3 обов’язкових параметра:

e-mail одержувача;

тема повідомлення;

тіло повідомлення.

Також є ще один необов’язковий параметр, який відповідає за заголовки. У ньому можна вказати кодування, в якій буде надіслано повідомлення. Відповідно, програма буде знати, в якому кодуванні необхідно відкривати отримане повідомлення. Якщо кодування не вказувати, то повідомлення буде відкрито в кодуванні поштової програми за промовчанням.

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

0 OR empty($_SESSION[‘ip’])){
$to = ‘[email protected]’;
$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’] = ‘

Повідомлення відправлено!

‘;
header(«Location: index.php»);
exit;
}else{
$to = ‘[email protected]’;
$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’] = ‘

Повідомлення відправлено!

‘;
header(«Location: index.php»);
exit;
}else{
$_SESSION[‘res’] = ‘

Помилка!

‘;
header(«Location: index.php»);
exit;
}
}
}
?>

Ім’я:
Повідомлення:

Висновок

От і все. Тепер у випадку, якщо форму заповнює користувач з «чорним» IP, повідомлення буде відправлено з відповідною поміткою в темі повідомлення. Таким чином, поставлена нами завдання реалізована повною мірою і, як бачимо, нічого складного тут немає.

На цьому наш урок закінчено. Удачі і до нових зустрічей!