Установка времени жизни для кэшированных станиц сеанса (в минутах).
session.cookie_domain
none
Домен для установки в cookie-наборе сеанса.
session.cookie_lifetime
Определяет продолжительность существования cookie-набора идентификатора сеанса на машине пользователя. По умолчанию 0 — пока не будет закрыт браузер.
session.cookie_pafh
/
Путь для установки в cookie-наборе сеанса.
session.name
PHPSESSID
Имя сеанса, которое в системе пользователя используется как имя cookie-набора.
session.save_handler
файлы
Определяет место хранения данных сеанса. Здесь можно указать базу данных, однако для этого потребуется реализовать собственные функции.
session.save_path
/tmp
Путь к месту хранения данных сеанса. В более общем случае для определения и обработки передаваемых на хранение аргументов используется session.save_handler.
session.use_cookies
1 (разрешить)
Конфигурация сеанса с возможностью использования cookie-наборов на стороне клиента.
Выполнение аутентификации пользователей средствами управления сеансом.В завершение рассмотрим более важный пример использования контроля сеанса.
Наиболее часто, пожалуй, управление сеансом применяется в целях отслеживания пользователей после того, как они были аутентифицированы через механизм входной регистрации. В предлагаемом примере можно видеть, как эти функциональные возможности обеспечиваются за счет сочетания аутентификации при помощи базы данных MySQL и использования механизма управления сеансом.
В нашем примере мы воспользуемся базой данных аутентификации, которая была создана ранее. Это требуется для работы с модулем mod_auth_mysql. Пример включает три простых сценария. Первый, authmain.php, обеспечивает форму для входной регистрации и аутентификации пользователей Web-сайта. Второй, members_only.php, представляет информацию только для тех пользователей, которые успешно прошли входную регистрацию. Третий, logout.php. реализует выход пользователей из системы.
Первая страница предоставляет пользователю возможность войти в систему. В случае, если он предпримет попытку получить доступ к секции Members, не пройдя входную регистрацию, будет выдано сообщение. Если же пользователь сначала прошел входную регистрацию (с именем пользователя: testuser и паролем: test123, как было задано ранее), а потом попытался войти на страницу Members, он увидит соответствующее сообщение.
Давайте посмотрим на код приложения. Большая часть кода сосредоточена в сценарии authmain.php, приведенном в листинге 6.18. Давайте изучим его более подробно.
Листинг 6.18.authmain.php — Основная часть приложения аутентификации
session_start();
if ($userid && $password)
{
// если пользователь как раз пытается зарегистрироваться
Данный сценарий отличается сложной (в разумных пределах) логикой, но иначе нельзя: ведь он осуществляет представление формы для входной регистрации и ее обработку.
Работа этого сценария сосредоточена вокруг переменной сеанса $valid_user. Основная идея здесь заключается в следующем: если кто-либо успешно прошел процедуру входной регистрации, мы регистрируем переменную сеанса с именем $valid_user, которая содержит идентификатор пользователя.
Так что же первым делом выполняется в сценарии? Правильно, вызов session_start(). Эта функция загружает переменную сеанса $valid_user, если последняя была зарегистрирована.
При первом проходе по сценарию ни один из условных операторов if не сработает и неудачливому пользователю к концу сценария останется лишь внимательно прочесть сообщение о том, что он не прошел процедуру входной регистрации. После этого мы предоставляем ему форму, при помощи которой он сможет это сделать:
Когда пользователь нажмет кнопку отправки (Submit), сценарий вызывается заново и вновь все начинается с начала. На этот раз в нашем распоряжении будут имя пользователя и пароль, позволяющие его аутентифицировать (они хранятся в $userid и $password). Если эти переменные установлены, переходим к блоку аутентификации:
if ($userid && $password) {
// если пользователь как раз пытается зарегистрироваться
."where name='$userid' " . " and pass=password('$password')";
$result = mysql_query($query, $db_conn);
И вот мы подключаемся к базе данных MySQL и проверяем имя пользователя и пароль. Если в базе данных существует соответствие этой паре, мы регистрируем переменную $valid_user, которая содержит идентификатор для конкретного пользователя. Таким образом, мы знаем, кто вошел в систему и, соответственно, будем его отслеживать.
if (mysql_num_rows($result) >0) {
// если пользователь найден в базе данных,
// зарегистрировать его идентификатор
$valid_user = $userid;
session_register("valid_user"); }
Поскольку уже известно, кто сейчас посещает сайт, то повторно предоставлять ему aорму входной регистрации нет необходимости. Вместо этого мы сообщаем пользователю, что мы знаем, кто он такой, и даем ему возможность выхода из системы:
if (session_is_registered("valid_user")) {
echo "You are logged in as: $valid user <br>";
echo "<a href=\"logout.php\">Log out</a><br>"; }
Если же при попытке произвести входную регистрацию пользователя, мы по какой-то причине терпим неудачу, то у нас имеется идентификатор пользователя, но нет переменной $valid_user, и ничего не остается, кроме как выдать сообщение об ошибке:
if (isset($userid)) {
// если пользователь пытался зарегистрироваться, но возникла ошибка
echo "Could not log you in"; }
Поскольку $valid_user является зарегистрированной переменной сеанса, ее нельзя перезаписать путем передачи другого значения через URL, например так:
members_only.php?valid_user=testuser
С основным сценарием, похоже, все понятно. А теперь посмотрим на страницу Members. Код этого сценария показан в листинге 6.19.
echo "<p>Only logged in members may see this page.</p>";
}
echo "<a href=\"authmain.php\">Back to main page</a>";
?>
Приведенный выше код очень прост. Все, что он делает — это запуск сеанса и проверка того, содержит ли текущий сеанс зарегистрированного пользователя, с использованием функции session_registered_user(). Если пользователь прошел процедуру входной регистрации, мы отображаем содержимое сайта для зарегистрированных пользователей, в противном случае мы сообщаем ему, что у него нет соответствующих полномочий.
И в завершение рассмотрим сценарий logout.php, который завершает регистрацию пользователя в системе. Код сценария показан в листинге 6.20.
Листинг 6.20.logout.php —отмена регистрации переменных сеанса и завершение сеанса
<?
session_start();
$old_user = $valid_user; // сохранить для проверки,
// регистрировался ли пользователь
$result = session_unregister("valid_user");
session_destroy();
?>
<html><body><h1>Log out</h1>
<?
if (! empty ($old_user) ){
if ($result){
// если пользователь был зарегистрирован и не покинул систему
echo "Logged out.<br>"; }
else { // если пользователь не может покинуть систему
echo "Could not log you out.<br>"; } }
else { // если пользователь не был зарегистрирован,
echo "You were not logged in, and so have not been logged out <br>"; }
?>
Приведенный код очень прост. Мы запускаем сеанс, запоминаем старое имя пользователя, отменяем регистрацию переменной $valid_user и завершаем сеанс. После этого мы выдаем пользователю одно из следующих сообщений: он вышел из системы, не может выйти из системы или не может выйти из системы, поскольку первоначально даже не регистрировался.
Примеры программ.
Системы управления содержимым очень эффективны для Web-сайтов, где содержимое поддерживается не только одним автором, либо сопровождение осуществляет не технический персонал, либо содержимое и графическое оформление разрабатывается различными людьми или отделами.
Мы создадим приложение, помогающее уполномоченным пользователям управлять интеллектуальной собственностью организации в электронном виде.
Требования к проекту.Необходимо создать систему, которая:
· Увеличивает продуктивность работы, позволяя авторам сконцентрироваться на статьях, а дизайнерам — на оформлении
· Позволяет редактору просматривать статьи и выбирать их для публикации
· Создает единообразное восприятие сайта с помощью шаблонов страниц
· Предоставляет авторам доступ только к предназначенным для них областям сайта
· Позволяет легко изменять оформление любого раздела либо всего сайта
· Предотвращает изменение нового содержимого
Редактирование содержимого.Во-первых, необходимо продумать способ ввода содержимого в систему, а также методы его хранения и редактирования. Требуется выбрать метод передачи компонентов статей и оформления. Существует три возможности.
1. FTP. Авторам и дизайнерам можно предоставить FTP-доступ к областям Web-сервера. Это позволит им загружать на сервер файлы со своих локальных компьютеров. Для загружаемых файлов потребуется выработать строгий стандарт именования (для идентификации принадлежности изображений к статьям). Вместо этого можно применить основанную на Web систему, которая будет осуществлять идентификацию независимо от FTP-загрузки. Использование FTP создает проблему допусков. Необходимая для данного примера гибкость не позволяет использовать FTP для предоставления пользователям возможности загружать файлы.
2. Метод загрузки файлов. HTTP-протокол предоставляет метод загрузки файлов при помощи Web-браузера. Язык РНР позволяет решать эту задачу очень просто. Кроме того, метод загрузки файлов дает возможность хранить текст в базе данных вместо файлов. Для этого выполняется чтение во временный файл и сохранение его содержимого в базе данных, а не копирование в другую область файловой системы. Метод загрузки файлов в этом проекте не используется.
3. Интерактивное редактирование. Пользователи могут создавать и редактировать документы без участия FTP либо другого метода загрузки файлов. Вместо этого авторам можно предоставить в окне большое текстовое поле, в котором они смогут редактировать содержимое статей. Этот метод прост, но часто эффективен. Web-браузер не предоставляет каких-либо возможностей редактирования текста, кроме функций копирования и вставки, присущих операционной системе. Однако, когда требуется внести лишь небольшое изменение, например, исправить орфографическую ошибку, это можно осуществить очень быстро. Как и для метода загрузки файлов, данные формы можно записать в файл либо сохранить в базе данных.
Преимущество баз данных перед файлами для хранения содержимого.На начальном этапе необходимо принять важное решение относительно метода хранения содержимого после его загрузки в систему.
Поскольку совместно с текстом хранятся метаданные, мы решили поместить текстовую часть содержимого в базу данных. Хотя MySQL способен хранить мультимедийные данные, принято решение хранить загружаемые изображения в файловой системе. Использование большого двоичного объекта (BLOB) в базе данных MySQL может снизить быстродействие.
В базе данных будут храниться лишь имена файлов изображений. Дескриптор <IMG SRC> может прямо ссылаться на каталог графических файлов обычным образом.
Когда объем данных велик, важно оптимизировать их хранение. Подобно тому, как эффективность базы данных зависит от правильной индексации, файловая система существенно выигрывает от хорошо продуманной системы каталогов.
Рис. 6.1. Структура каталогов для загрузки файлов
В данном случае файловая система содержит каталоги, представляющие первую букву каждого имени файла. Таким образом, файлы распределены по 26 каталогам. Это существенно ускоряет доступ по сравнению с ситуацией, когда все файлы хранятся в одном каталоге. Важно отметить, что имена файлов должны генерироваться сценарием обработки загрузки таким образом, чтобы гарантировалась их уникальность.
Структура документов.В качестве примеров статей будет использоваться краткий текст новостей, включающий один-два абзаца и единственное изображение. Он предназначен для тех, кто спешит. Подобные документы с заголовком, абзацами и иллюстрацией можно считать структурированными. Чем выше степень структурирования документа, тем проще его разбить на составляющие, хранимые в базе данных. Преимущество такого подхода состоит в возможности единообразного структурированного представления документов.
В качестве примера возьмем статью новостей. Заголовок будет храниться в своем поле отдельно от текста. Изображение по своей природе является отдельным компонентом документа. Поскольку заголовок является отдельным элементом, для его отображения можно задать стандартный шрифт и стиль, а также легко отделить заголовок от остальной части статьи, сформировав главную страницу заголовков.
Для крупных документов можно применить к отдельным абзацам отношение один ко многим. Другими словами, каждый абзац будет храниться в отдельной строке базы данных и иметь связь с идентификатором главного документа. Этот вид динамической структуры документа позволит представлять страницу содержания для каждого документа и отображать каждый раздел независимо либо отображать документ целиком.
Использование метаданных.Уже решено, что запись для каждой статьи содержит заголовок, текст и изображение. Однако ничто не мешает хранить в той же записи другие данные. Система автоматически вставляет значения, описывающие авторство статьи и время ее последней модификации. Они могут автоматически отображаться в нижней части статьи и служить подписью и меткой времени, избавляя автора от необходимости добавления этой информации. Кроме того, иногда полезно добавлять неотображаемые данные, называемые метаданными. Хорошим примером служит хранение ключевых слов, которые будут использоваться в качестве индексов поискового механизма.
Поисковый механизм будет извлекать ключевое слово для каждой статьи и на его основе определять соответствие критериям поиска. Это устраняет необходимость сканирования всего текста каждой статьи. Администратор сайта сможет управлять соответствием ключевых слов и фраз определенным документам.
В нашем примере допускается связывать со статьей любое количество ключевых слов, а также присваивать каждому ключевому слову "весовое" значение, указывающее степень его значимости в диапазоне от 1 до 10.
Затем можно разработать алгоритм поискового механизма, который располагает соответствия статьям согласно человеческой шкале значимости. Это заменит сложный алгоритм, который интерпретирует английский текст и принимает решения в зависимости от своего ограниченного понимания, а также управляется фиксированными правилами.
Метаданные должны храниться в базе данных. Можно использовать HTML-дескриптор <МЕТА> либо даже применять XML для создания документов. Однако лучше при любой возможности воспользоваться преимуществами базы данных для управления документами.
Форматирование вывода.В нашем примере сайта новостей страницы отображаются в простом, но структурированном формате. Каждая страница содержит ряд статей, сформатированных одинаково. Прежде всего, заголовок выводится крупным шрифтом, внизу слева отображает фотография, а справа — текст статьи. Страница целиком содержится в стандартном шаблоне страниц, что создает последовательность в оформлении сайта.
<TABLE>
<TR><TD COLSPAN=2>TOP ВАR</ТD></TR>
<TR><TD> Side menu </TD><ТD>
MAIN CONTENT CELL
</TD></TR> </TAВLЕ>
Рис. 6.2. Логическая структура страницы.
Этот вид компоновки крайне популярен — сколько сайтов вы регулярно посещаете, где панель меню расположена слева, а ссылки быстрого доступа вверху? При этом средства навигации остаются неизменными независимо от просматриваемой страницы.
Реализация структуры шаблонов, подобной той, что используется для оформления страниц, очень проста. В HTML-коде можно найти дескриптор <TD>, начинающий ячейку главного содержимого. В этом месте HTML-код расщепляется на два файла. Первая половина составляет файл заголовка, а вторая — нижний колонтитул. Когда отображается страница, сначала выводится заголовок, затем текст и, наконец, нижний колонтитул.
Реализация сайта с шаблоном заголовка и нижнего колонтитула позволяет модифицировать оформление сайта, изменяя файлы шаблонов.
РНР предоставляет две опции конфигурации, которые удобны в данной ситуации. Можно определить для каждого каталога директивы auto_prepend_file и auto_append_file, которые указывают файлы, подключаемые до или после выполнения любого сценария.
Однако существуют некоторые ограничения. Если существуют сценарии, которые не генерируют вывод и отправляют заголовок переадресации, такой как
<? header("Location: destination.php"); ?>
файлы заголовка и нижнего колонтитула будут отображаться, а переадресация не произойдет, поскольку вывод уже отправлен в Web-браузер. Это также создает проблемы с cookie-наборам и встроенными функциями управления сеансами РНР 4, поскольку cookie не будет правильно функционировать после отправки вывода Web-браузеру.
Управление изображениями.Авторы могут дополнять статьи своими фотографиями. Нам необходимо единообразие оформления, но что произойдет, когда один автор загрузит крупное изображение высокого качества, а другой — свернутую в пиктограмму картинку?
Исходя из предположения, что изображения в основном представляют собой фотографии, можно ограничиться лишь форматом JPEG и воспользоваться РНР-функциями для управления графикой.
Напишем небольшой сценарий resize_image.php, который на лету изменяет размер изображений, в результате чего они могут отображаться с помощью дескриптор <IMG SRC>. Сценарий приводится в листинге 6.21.
Листинг 6.21. Сценарий resize_image.php изменяет размеры JPEG-изображения "на лету"
Этот сценарий принимает три параметра — имя файла изображения, максимальную ширину и высоту в точках. Не стоит полагать, что если указан максимальный размер 200 х 200, изображение будет масштабировано в соответствии с этими значениями. Его масштаб будет уменьшен пропорционально таким образом, чтобы указанные максимальные размеры не превышались. Например, изображение размером 400 х 300 будет уменьшено до размера 200x150. Таким образом достигается сохранение пропорций изображения.
Изменение размера изображения на сервере предпочтительнее, чем простое задание атрибутов HEIGHT и WIDTH в дескрипторе <IMG SRC>. Размер большого изображения с высоким разрешением может составлять несколько мегабайт. Если же картинку уменьшить до приемлемых размеров, ее размер может не превышать 100 Кб. Нет надобности загружать файл большого размера, а затем указывать браузеру изменить размер изображения.
Здесь используется функция ImageCopyResized() для масштабирования изображений на лету. Суть операции изменения размера состоит в вычислении новых параметров ширины и высоты. Определяется соотношение между реальными и максимальными размерами. Параметры $max_width и $max_height могут быть переданы в одной строке запроса. Иначе будут использованы стандартные значения, указанные в верхней части листинга.
Если изображение уже меньше указанных максимальных размеров, его ширина и высота остаются неизменными. В противном случае будет использован коэффициент X или Y для равного масштабирования обоих размеров, чтобы изображение уменьшенного размера не оказалось растянутым либо сплющенным:
if ( ($width <= $max_width) && ($height <= $max_height) )