AJAX
Аякс (AJAX) это довольно просто, на много проще, чем кажется на первый взгляд. Сногсшибательный эффект от его применения повергает многих в уныние - мол мне так никогда не сделать. На самом же деле ничего особо делать и не нужно, все давно сделано.
И так, что же такое аякс. Аякс, это не язык программирования, это технология асинхронных запросов. То есть это тоже самое, как отправка данных из формы на сервер. Только из формы данные отправляются одновременно с перезагрузкой страницы, а аякс позволяет отправить их и принять ответ сервера фоном, не трогая страницу вообще.
Как это делается.
Сначала отправка данных. Для того, что бы отправить запрос, создадим в JAVASCRIPT объект:
var req = Create();
function Create(){
if(navigator.appName == "Microsoft Internet Explorer"){
req = new ActiveXObject("Microsoft.XMLHTTP");
}else{
req = new XMLHttpRequest();
}
return req;
}
Эти танцы с бубном нужны для кроссбраузерности, что бы его понимали все браузеры. Дальше нам нужна функция, которая отправит запрос на сервер. Вот она:
это сам запрос. Сначала определяем метод отправки данных. Предпочтительнее POST, так как он не имеет ограничений по количеству передаваемых символов. Дальше адрес приемника, то есть скрипта, которому запрос адресован. Это тоже самое, что action в форме.Следом - true. Это команда продолжать скрипт вне зависимости от того, отправлен запрос или нет.
Дальше, вот тут:
req.onreadystatechange = Refresh;
мы определяем функцию (Refresh()), которая будет вызвана после отправки запроса. Она и примет ответ сервера.
Вот это:
отправка заголовка. Браузер всегда отправляет заголовки, прежде чем отправить данные. Для того, что бы сервер знал, что ему ждать и в какой кодировке. Кодировка у аякса должна быть utf-8, иначе могут возникнуть проблемы.
Ну а это:
req.send(query);
непосредственно сама отправка запроса, то же самое, что кнопка submit в форме. В переменной query должны содержаться данные для сервера. Формируются они так.
Допустим нужно отправить содержимое текстового поля. Получим его в скрипт и сформируем строку запроса:
function Pusk()
{
var txt = encodeURIComponent(document.getElementById('txt').value);
var query = 'txt='+txt;
Request(query)
}
Запись 'txt='+txt обозначает, что POST переменной txt присвоено значение из js переменной txt. То есть содержимое текстового поля, которое мы получили методом getElementById. Тут есть маленькая тонкость. Если нужно передать несколько переменных, то их нужно раздеять амперсандом, так же как в URL:
var query = 'txt1='+txt1+'&txt2='+txt2;
но если в тексте попадется амперсанд, то все нарушится. Так же аякс реагирует на + = и кое что еще. Что бы этого избежать, нужно данные перед отправкой закодировать, что мы и сделали:
Дальше нам нужно принять ответ сервера. Для этого напишем функцию:
function Refresh()
{
var a = req.readyState;
if( a == 4 )
{
var b = req.responseText;
document.getElementById('ajax').innerHTML = b;
}
else
{
document.getElementById('ajax').innerHTML = '<img src="prel.gif" />';
}
}
которая будет вызвана после отправки запроса. Мы это уже проходили (см выше)
Что тут. Сначала мы смотрим состояние связи. Нас интересует 4, потому что это обозначает - ответ принят и загружен. Получить его можно методом req.responseText ну и прописать в какой нибудь приемник, допустим div. А пока ответ не получен, в этот приемник для красоты нарисуем какой нибудь индикатор.
Вот и всё, весь аякс. Осталось на сервере принять запрос, обработать его и выдать результат, все точно так же, как и при обычном взаимодействии.
Вот что у нас получилось:
<html>
<head>
<script type="text/javascript" language="javascript">
var req = Create();
function ge(id)
{
return document.getElementById(id);
}
function Create()
{
if(navigator.appName == "Microsoft Internet Explorer")
{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
req = new XMLHttpRequest();
}
return req;
}
function Request(query)
{
req.open('post', 'ajax.php' , true );
req.onreadystatechange = Refresh;
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
req.send(query);
}
function Refresh()
{
var a = req.readyState;
if( a == 4 )
{
var b = req.responseText;
document.getElementById('ajax').innerHTML = b;
}
else
{
document.getElementById('ajax').innerHTML = '<img src="prel.gif" />';
}
}
function Pusk()
{
var query;
query ='txt='+encodeURIComponent(ge('myid').value);
Request(query);
}
</script>
</head>
<body>
<div id="ajax"></div>
<input type='text' id='myid' ><br>
<input type="button" value="ТЫРЦ" onClick="Pusk()">
<img src="prel.gif" width="1" height="1" />
</body>
</html>
То есть мы принимаем данные и отправляем их обратно. Можно их обработать, занести в базу, достать что то другое и так далее, всё как обычно. Тут для наглядности мы усыпили скрипт на 3 секунды. Ну вот и всё, можете убедиться
Загрузка файлов
Часто возникает ситуация, когда нужно обеспечить пользователю возможность самостоятельно загрузить на сервер какой то файл. К примеру аватарку на форум.
Так вот - загрузка файлов не очень сложная операция на самом деле, если усвоить несколько моментов. Начнем по порядку.
Главное, чем отличается форма загрузки файлов от обычной формы, это атрибут ecntype="multipart/form-data", который как раз и указывает на то, что будет загружаться файл. Для загрузки файлов надо использовать метод post.
Тег input с атрибутом file позволяет пользователю выбрать загружаемый файл.
Далее пользователь выбирает файл и нажимает кнопку загрузить и за дело принимается скрипт file_upload.php
Как текстовые данные можно получить через суперглобальный массив $_POST, так и загруженные файлы через $_FILES['имя']. Где имя - значение атрибута name файлового поля . В нашем случае это name="userfile"
$_FILES['userfile'] представляет собой массив и содержит следующие элементы:
$_FILES['userfile']['name'] - имя файла указанное при загрузке
$_FILES['userfile']['type'] - тип mime (напр.: image/jpeg)
$_FILES['userfile']['tmp_name'] - путь к временному файлу.
$_FILES['userfile']['size'] - размер файла в байтах
$_FILES['userfile']['error'] - код ошибки
Что бы увидеть, что передается из этой формы на сервер, можно в обработчике выполнить этот скрипт:
file_upload.php
Ну это только посмотреть. А вот чтобы был толк, нужно сделать этот самый обработчик. Допустим мы хотим загрузить картинку (.jpg)
Сначала валидация (проверка загружаемого файла). Проверим, что файл был успешно загружен во временную папку. Это такая директория, куда складываются все поступившие файлы до их проверки и дальнейшего перемещения. Своего рода карантин. После отработки скрипта, эти файлы уничтожаются.
Если ошибки загрузки не было, то $_FILES['userfile']['error'] возвращает 0, что соответствует именованной константе UPLOAD_ERR_OK (Вот список всех возможных ошибок и их значений). Если же случилась какая-то бяка, то вычисляем ее и выводим соответствующее сообщение.
А вот и он, собственной персоной. Прямо в том же файле
file_upload.php
<?php
$errors = array();
$info = '';
if($_FILES['userfile']['error'] === UPLOAD_ERR_OK)
{
// если файл загружен без ошибок, то продолжим тут
}
else
{
// массив ошибок
$error_values = array(
UPLOAD_ERR_INI_SIZE => 'Размер файла больше разрешенного директивой upload_max_filesize в php.ini',
UPLOAD_ERR_FORM_SIZE => 'Размер файла превышает указанное значение в MAX_FILE_SIZE',
UPLOAD_ERR_PARTIAL => 'Файл был загружен только частично',
UPLOAD_ERR_NO_FILE => 'Не был выбран файл для загрузки',
UPLOAD_ERR_NO_TMP_DIR => 'Не найдена папка для временных файлов',
UPLOAD_ERR_CANT_WRITE => 'Ошибка записи файла на диск'
);
if(!empty($error_values[$_FILES['userfile']['error']]))
$errors[] = $error_values[$_FILES['userfile']['error']];
else
$errors[] = 'Случилось что-то непонятное';
}
В массив $errors будем записывать ошибки. А в $info сообщение, если загрузка прошла успешно.
Затем "более тонкая настройка". Проверка уже загруженного во временную директорию файла и перемещение его на постоянное место жительства.
// если файл загружен без ошибок, то продолжаем тут
// проверяем расширение файла
$file_extension = pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);
$valid_extensions = array('jpg', 'jpeg');
if(in_array($file_extension, $valid_extensions))
{
// проверяем размер файла
$max_file_size = 100000;
if($_FILES['userfile']['size'] < $max_file_size)
{
// если все ОК
$destination = 'images/'.$_FILES['userfile']['name'];
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $destination))
$info = 'Файл успешно загружен';
else
$error = 'Не удалось загрузить файл';
}
else
$error = 'Размер файла больше допустимого';
}
else
$error = 'У файла недопустимое расширение';
Проверим расширение. Сделаем это с помощью функции pathinfo(). Эта функции принимает в качестве параметра имя файла или путь к файлу и возвращает массив со следующими значениями:
dirname - путь к папке с файлом
basename - полное имя файла
extension - расширение файла
filename - имя без расширения ( с версии 5.2.0 )
Если нам нужно только одно из этих значений, то в опциях можем указать нужный флаг.
Например так - pathinfo($path, PATHINFO_EXTENSION) возвращает только расширение файла.
Затем проверяем его с помощью функции in_array().
Далее проверяем размер файла.
Если все прошло без ошибок, то перемещаем файл из временной папки в нужную нам. Для этого используем
move_uploaded_file($filename, $destination), где $filename - путь к файлу, который надо переместить, а $destination - путь, куда мы хотим сохранить наш файл вместе с именем.
При этом проверяем, что файл был действительно перемещен. Этому могут помещать, например, неправильно настроенные права на соответствующие папки. В Windows таких проблем практически не возникает, а вот в ОС *nix сплошь и рядом. Для нормальной работы папке, куда будут перемещаться файлы, нужно назначить права 777.
И в завершении выводим сообщение об ошибке или об успешной загрузке файла.
// выводим сообщение о результате
echo !empty($error) ? $error : '';
echo !empty($info) ? $info : '';
Но будет лучше и удобнее, если это оформить функцией.
Это самый простой загрузчик, он позволяет загружать любые файлы, не только картинки. Допустим архивы. Стоит только указать нужное расширение.
Попозже мы рассмотрим, как работать с картинками(ресайз, водный знак и так далее).
Капча
Очень часто при регистрациях или просто каких то активных действиях нам предлагается ввести в поле код, нарисованный на картинке.
Вот это и есть так называемая CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) или по русски - капча.
Для чего это нужно.
Дело в том, что при автозаполнении формы (роботом или ботом, как сейчас принято говорить), у спамеров возникает трудность - распознать эту надпись. У робота нет глаз и ассоциативного мышления, он может только провести попиксельный анализ картинки. Это далеко не всегда бывает успешным, так как создаются всевозможные помехи и искажения, которые человеческий мозг, в силу своей продуктивности, спокойно отсеивает, а глупый бот не может.
Но соблазн воспользоваться раскрученными ресурсами, как рекламными площадками своей гнусной деятельности у спамеров велик, и они давно научились распозновать основные виды популярных капчь. По этому, одним из эфективных способов защиты является самодельная капча, такая, какой нет у других. Писать анализатор для одного сайта бывает довольно хлопотно и накладно, так что некоторое время можно будет спать спокойно.
Правда нужно отдавать себе отчет в том, что сложная капча на форме регистрации по статистике отпугивает до 70% потенциальных пользователей. Но иногда это бывает действительно необходимо.
Вот сейчас я покажу принцип, по которому можно построить собственную капчу. За одно познакомимся с некоторыми возможностями графической библиотеки GD.
Начнем со скрипта, строющего эту самую картинку с несколькими буквами/цифрами (в нашем случае их будет 5).
Алгоритм создания капчи можно представить в виде:
1. Создать некую строку из случайных символов.
2. Создать пустое изображение или загрузить фон из файла.
3. Нарисовать на этом изображении помехи (случайные точки, линии).
4. Написать строку на этом изображении.
5. Сохранить эту строку в сессии (позднее будет использован для проверки, верно ли ввел пользователь код с картинки).
6. Показать изображение.
Код будет полностью соответствовать данному алгоритму.
<?php
// Начинаем сессию, далее мы добавим в нее ключ
session_start();
// Получаю строку из пяти случайных символов
$string = getRandomString(5, 'lower');
// Задаем размеры капчи (самой картинки) в пикселях
$width = 108;
$height = 25;
// Строим пустое изображение. К высоте добавляется 15 пикселей, это будет белая
// полосочка снизу с текстом "press to change"
$captcha = imagecreatetruecolor($width, $height + 15);
// Получаю случайный цвет для фона
$bg = imagecolorallocate($captcha, mt_rand(10, 50), mt_rand(10, 50), mt_rand(10, 50));
// Определяю цвет фона для строки
$font_color = imagecolorallocate($captcha, mt_rand(220, 255), mt_rand(220, 255), mt_rand(220, 255));
$white = imagecolorallocate($captcha, 255, 255, 255);
$black = imagecolorallocate($captcha, 0, 0, 0);
// Заливаю капчу цветом фона, но оставляю снизу белую полоску
imagefill($captcha, 0, 0, $white);
imagefilledrectangle($captcha, 0, 0, $width, $height, $bg);
// "Разбрасываю" в случайном порядке четыре линии по капче. Цвета линий тоже
// определяются случайно
for ($i = 0; $i < 4; $i++)
{
// Создаю случайный цвет для очередной линии
$color = imagecolorallocate($captcha, mt_rand(170, 255), mt_rand(170, 255), mt_rand(170, 255));
// Черчу линию между двумя случайными точками
imageline(
$captcha,
mt_rand(0, $width - 1),
mt_rand(0, $height - 1),
mt_rand(0, $width - 1),
mt_rand(0, $height - 1),
$color
);
}
// Пишу эту случайную строку в капче
imagestring($captcha, 5, 33, 4, $string, $font_color);
// Указание пользователю
$how_refresh = 'press to change';
imagestring($captcha, 3, 2, 26, $how_refresh, $black);
// Сохраняю строку в сессии
$_SESSION['key'] = $string;
// Отсылаем заголовок браузеру, что ему сейчас будет передана картинка
header('Content-type: image/png');
// Отсылаем картинку в стандартный выходной поток (в браузер)
imagepng($captcha);
/**
* Генерирует строку случайных символов
*
* @param int $length - длина строки
* @param string $case - регистр генерируемых символов, может быть lower, upper,
* both. Если не передан ни один из вышеперечисленных, то
* используется lower
* @return string - строка, состоящая из случайных символов заданной длины
*
*/
function getRandomString($length, $case = 'lower')
{
/* Латинские символы, похожие на символы кирилицы:
* в ниженем регистре: a b c e o p x l
* в верхнем регистре: A B C E H K M O P T X
*/
$ban_chars = array('a', 'b', 'c', 'e', 'o', 'p', 'x', 'l',
'A', 'B', 'C', 'E', 'H', 'K', 'M', 'O', 'P', 'T', 'X');
// В зависимости от $case формирую массив диапазонов символов, из которых
// можно выбирать
switch ($case)
{
case 'upper':
$random_chars = range('A', 'Z');
break;
case 'both':
$random_chars = array_merge(range('a', 'z'), range('A', 'Z'));
break;
case 'lower':
default:
$random_chars = range('a', 'z');
break;
}
// Добавляю цифр (ноль похож на O_o, по этому игнорируем)
$random_chars = array_merge(range(1, 9), $random_chars);
// Удаляю неоднозначные символы
$random_chars = array_diff($random_chars, $ban_chars);
// Перемешиваю массив
shuffle($random_chars);
// Беру первые $length элементов
$chars = array_slice($random_chars, 0, $length);
// Соединяю их в строку и - марш на выход.
return implode('', $chars);
}
Надеюсь с процессом создания капчи все было понятно. Идем далее, создайте файл index.php и поместите в него следующий код:
<?php
session_start();
// В переменной $status хранится подсказка для пользователя, которая потом будет
// отображаться в форме
$status = 'Введите текст с картинки';
if (isset($_POST['submit']))
{
// Сравниваем то, что ввел пользователь с ключем в сессии
if (!empty($_SESSION['key']) && ($_SESSION['key'] == $_POST['txtCaptcha']))
{
// Тут можно, нет, даже нужно поместить код, который будет выполняться
// в случае правильного ввода капчи, например добавить пост в гостевую
// книгу
$status = 'Правильно!';
}
else
{
// Ну а тут, соответственно, что делается в случае ошибки
$status = 'Вы ошиблись :-(';
}
}
Основная логика уже сделана, ничего сложно в этом не было. Теперь осталось сделать форму.
Вот тут одна изюминка. Дело в том, что иногда бывает действительно трудно прочитать, что же там написано. И по этому нужно дать возможность сменить картинку. Мы сделаем это с помощью JavaScript, просто заменив src у картинки. Но если вдруг скрипты у клиента отключены, то такой возможности не будет.
Так вот такая хитрость. Выведем капчу не в виде простой картинки, а в виде тега тип image.
<?php
session_start();
// В переменной $status хранится подсказка для пользователя, которая потом будет
// отображаться в форме
$status = 'Введите текст с картинки';
if (isset($_POST['submit']))
{
// Сравниваем то, что ввел пользователь с ключем в сессии
if (!empty($_SESSION['key']) && ($_SESSION['key'] == $_POST['txtCaptcha']))
{
// Тут можно, нет, даже нужно поместить код, который будет выполняться
// в случае правильного ввода капчи, например добавить пост в гостевую
// книгу
$status = 'Правильно!';
}
else
{
// Ну а тут, соответственно, что делается в случае ошибки
$status = 'Вы ошиблись :-(';
}
}
$login = !empty($_POST['login']) ? $_POST['login'] : NULL;
?>
Это кнопка в виде картинки, работает как submit, то есть отправляет форму. На onClick кнопки повешаем перехват события. То есть если JS включен, то событие отправки формы будет остановлено (return false) и страница перегружаться не будет.
А если скрипты отключены, то форма отправится. А так как она у нас в одном файле с обработчиком, данные вернутся и никто ничего не потеряет.
Вот и всё. Вот так она работает:
Ваше имя
Введите текст с картинки
текст:
Сам скрипт генерирующий капчу довольно прост, можно его усложнить, добавив загрузку фона, вместо создания пустого изображения, можно добавить случайных точек, можно писать текст буквами разных размеров и под разным углом, можно использовать ttf шрифт, можно слово не генерировать случайным образом а выбирать из файла, можно вообще еще много чего придумать на самом деле :-)
Базовая аутентификация
Базовая аутентификация - простейший вид защиты каталогов на сайте. Но не смотря на её простоту, она достаточно надежна для того, чтобы спать спокойно, не опасаясь за сокровища, которые хранятся на сайте.
Давайте рассмотрим, как это можно сделать.
Вариант 1. Защита одним файлом без использования БД
Раз мы не используем базу данных, то значит аутентификационные данные будут хранится в файле. Чтобы они не стали достоянием общественности, файл должен быть исполняемым, то есть иметь расширение .php Очень удобно хранить данные в виде массива, потому что сразу видна принадлежность пароля к логину. Пароль от греха лучше захэшировать, хуже от этого точно не станет. Чтобы это сделать, можно просто выполнить такой код:
<?php
echo md5('тут_пароль');
То, что получится, и есть хэш. Теперь собственно сам массив. Можно в него добавлять кучу данных, по числу доверенных лиц.
Положим этот скрипт рядом с защитой, а именно в файл auth.php
Теперь приступим, собственно, к созданию файла, который будет отвечать за аутентификацию. Для этого вида авторизации нужно отослать броузеру клиента такие заголовки:
WWW-Authenticate: Basic realm=\"Подпись на окне\"
HTTP/1.0 401 Unauthorised
Браузер выдаст окошко для ввода логина и пароля. Введённые данные будут помещены в суперглобальный массив: логин в переменную $_SERVER['PHP_AUTH_USER'], а пароль - в $_SERVER['PHP_AUTH_PW']. Теперь можно посмотреть это в деле. То есть, если пользователь не авторизован, то пускай наш сценарий посылает ему запрос на авторизацию:
Окошко получено, теперь нужно сравнить то, что в него будет введено, с тем, что имеется в файле с данными.
// Подключаем файл с аутентификационными данными
include './auth.php';
// Устанавливаем ключ входа
$key = false;
// Сверем данные аутентификации с полученными от юзера
if(isset($admins[$_SERVER['PHP_AUTH_USER']])
&& md5($_SERVER['PHP_AUTH_PW']) === $admins[$_SERVER['PHP_AUTH_USER']])
$key = true;// Если пара совпала, переустанавливаем ключ
Ну а что бы не посылать сразу лесом, если человек ошибся, выдадим ему окошко еще раз.
<?php
// Если ключа так и нет, опять окно и стоп-машина.
if(empty($key))
{
// опять выдаем юзеру это окошко, что бы заполнил
header('WWW-Authenticate: Basic realm="Administrative resource"');
header ('HTTP/1.0 401 Unauthorized');
exit();
}
Теперь стоит поместить эти строки в начала любого файла и доступ к нему будет ограничен узкому кругму лиц.
Вариант 2. Защита одним файлом с использованием БД
Она почти не отличается от той, которую мы только что рассмотрели. Разница в том, что данные будут хранится не в файле, а в базе данных
Первым делом нужно создать MySQL-таблицу, где будут храниться логины админов и их пароли. Таблица будет такая:
CREATE TABLE `adminc` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user` VARCHAR(50) NOT NULL,
`password` TINYTEXT NOT NULL,
PRIMARY KEY (`id`)
);
Теперь занесём данные в таблицу (пароль шифруем так же, как и раньше):
При желании в дальнейшем можно будет добавить ещё пользователей. Но пока только один. 'admin' => 'admin'
Теперь выведем в нашей программе запрос к базе данных при введении логина и пароля, экранируя специальные символы для этого запроса при вводе логина. Пароль экранировать не нужно, функция md5() не пустит ничего лишнего.
Нужно помнить о магических кавычках, иначе будет двойное экранирование.
А если при выборке в таблице не будет обнаружено записи по заданным условиям, то снова покажем окно для авторизации:
<?php
mysql_connect('localhost', 'root', '');
mysql_select_db('DBname');
if(empty($_SERVER['PHP_AUTH_USER']))
{
header('WWW-Authenticate: Basic realm="Administrative resource"');
header("HTTP/1.0 401 Unauthorised");
exit();
}
$result = mysql_query("SELECT COUNT(*) AS `cnt` FROM `adminc`
WHERE user='". mysql_real_escape_string($_SERVER['PHP_AUTH_USER']) ."'
AND password='". md5($_SERVER['PHP_AUTH_PW']) ."'"
);
if (mysql_result($result, 0) == 0)
{
header('WWW-Authenticate: Basic realm="Administrative resource"');
header ("HTTP/1.0 401 Unauthorized");
exit();
}
Ну а дальше все точно так же, пишем это первыми строками и спим спокойно.
Вариант 3. Защита при помощи .htaccess и .htpasswd. В данном случае нужно создать два файла: один .htaccess, другой - с логинами и паролями. Первый файл положим в директорию, доступ к которой нужно ограничить. Что там можно написать?
Строчка "AuthType Basic" будет указывать метод шифровки пароля.
"AuthName "Надпись в окошке" " - здесь просто указывается, какая надпись будет выдана в форме.
"AuthUserFile /путь к файлу/.htpasswd" - путь к файлу с паролями. Общепринято называть такие файлы .htpasswd (хотя это и не обязательно).
"require valid-user" - эта строка сообщает, что доступ к директории будет открыт всем пользователям, чьи логины и пароли есть в .htpasswd-файле. Чтобы, к примеру, дать доступ конкретным пользователям (например, Admin), нужно написать "Require user Admin" (остальных, если потребуется, можно указать через пробел).
Итак, у нас получился .htaccess-файл такого вида:
AuthType Basic
AuthName "Administrative resource"
AuthUserFile /путь к файлу/.htpasswd
require valid-user
Теперь нужно создать файл с паролями. Создаётся он при помощи утилиты htpasswd (файл htpasswd.exe), входящей в состав сервера Apache и лежащей в папке bin. По сути это обычный текстовой файл, однако создать его вручную не получится - пароль хранится в зашифрованном виде, а шифровку реализует как раз эта самая программка.
Примечание.
Если у Вас стоит пакет Денвер, то в нем нет такой утилиты. Выход прост. Берем её здесь и складываем по пути Z:\usr\local\apache\
Теперь все готово.
В Windows можно добраться до htpasswd, используя, например, Total или Windows Commander.
Нужно перейти в директорию, где хранится утилита, и набрать в командной строке это:
htpasswd -cm .htpasswd admin
Жмем "enter", получаем такое окошко:
Вводим и повторяем пароль и жмем ввод.
Всё, файл создан.
Это будет текстовой файл внутри которого храниться логин и через двоеточие зашифрованный пароль. Вот так:
admin:$apr1$qf3.....$2xWCAZSUuAVXrnsnW4D071
Если встанет необходимость добавить в файл ещё логины с паролями, то надо проделать ту же самую процедуру, но из команды на создание нового логина просто убрать ключ "с". Вот так:
htpasswd -m .htpasswd admin2
Теперь этот файл нужно взять и положить туда, куда задумывалось с самого начала:
AuthType Basic
AuthName "Administrative resource"
AuthUserFile /путь к файлу/.htpasswd
require valid-user
Место для этого файла лучше выбирать выше корневой директории, куда нет доступа по протоколу HTTP. Но если нет такой возможности, то лучше положить его в отдельную папку и защитить её тем же самым сервером, положив в неё .htaccess такого содержания:
deny from all
Ну вот и всё.
PS. Да, одна тонкость. Если PHP стоит не как модуль, а как CGI, то такая аутентификация работать не будет. Увы.
Занятость домена
Иногда бывает полезным на сайте иметь такую фишку:
Проверить занятость домена
Как это делается? На самом деле достаточно просто. Это всего навсего парсер ответов whois-серверов, которые отвечают за регистрацию доменов в своей зоне. Попробуем посмотреть, что это такое. Для этого напишем такой скриптик:
<?php
// Это адрес сервера, который и выдаст ответ
$whois = 'whois.verisign-grs.net';
// Это домен, который мы хотим проверить
$domain = 'irbis-team.com';
// Открываем сокет соединения
if($fp = @fsockopen($whois, 43))
{
// Отправляем запрос с проверяемым доменом
fputs($fp, $domain ."\n");
$answer = '';
// Получаем ответ
while(!feof($fp))
$answer .= fgets($fp, 128);
// Закрываем сокет
fclose($fp);
}
// Смотрим, что там интересного.
echo $answer;
Смотрим текст. Если домен зарегистрирован (как в нашем случае), тоначало будет примерно таким:
Whois Server Version 2.0 Domain names in the .com and .net domains
can now be registered with many different competing registrars.
Go to http://www.internic.net for detailed information.
Domain Name: IRBIS-TEAM.COM Registrar: .........
А если свободен, то таким:
Whois Server Version 2.0 Domain names in the .com and .net domains
can now be registered with many different competing registrars.
Go to http://www.internic.net for detailed information.
No match for "IRBIS-SHMIRBIS.COM"........
То есть разница в том, что если не занят, то будет присутствовать фраза "No match". Нам остается вычленить её из текста, и на основании её присутствия, сделать соответствующие выводы.
<?php
// Это адрес сервера, который и выдаст ответ
$whois = 'whois.verisign-grs.net';
// Это домен, который мы хотим проверить
$domain = 'irbis-shmirbis.com';
// Открываем сокет соединения
if($fp = @fsockopen($whois, 43))
{
// Отправляем запрос с проверяемым доменом
fputs($fp, $domain ."\n");
$answer = '';
// Получаем ответ
while(!feof($fp))
$answer .= fgets($fp, 128);
// Закрываем сокет
fclose($fp);
}
// Проверяем, есть ли нужная фраза
if(!preg_match('#No match#ui', $answer))
echo "Ваши кони тихо скачут";
else
echo "Повезло. Быстрее регай, пока ни кто не видел!";
Вот и вся кухня. Но это только по одной зоне .com Это не годится, что за полумеры... Нужно сделать полноценную проверку. Для этого соберем в массив адреса whois-серверов и ключевые фразы: