1. Постановка и анализ задачи
Постановка задачи: разработать интернет-приложение для организации электронной доски объявлений.
Исходные данные к работе: Windows98, интернет-сервер, наличие БД, доступ к приложению через WEB-интерфейс. Требуется организовать механизм регистрации и авторизации пользователей, возможность добавления, разделения по тематикам каталога, последующего редактирования и удаления объявлений, а так же подписку на почтовую рассылку объявлений. Предусмотреть режим администрирования с возможностью редактирования основных параметров приложения и разделов каталога доски объявлений, назначения прав доступа для зарегистрированных пользователей, а так же режим модерирования с возможностью удаления любого объявления из каталога.
Проведем анализ поставленной задачи: требуется разработать интернет-приложение для организации электронной доски объявлений. Электронная доска объявлений предназначена для небольших и средних коммерческих организаций, желающих бесплатно разместить рекламу своих товаров в сети интернет, а так же частных лиц, желающих продать или приобрести те или иные товары.
Приложение должно взаимодействовать с пользователями, то есть должно быть интерактивно, поэтому должно быть написано на одном из языков программирования web-сценариев, таких как Perl, PHP или других. Очевидно, что приложению потребуется оперировать с немалыми массивами данных, поэтому для их надежного хранения потребуется база данных, поскольку случай хранения информации непосредственно в файлах на сервере не является надежным и безопасным из-за проблем со множественным доступом. Приложение устанавливается на интернет-сервере, доступ пользователей к приложению осуществляется через WEB-интерфейс с помощью браузера, например MS Internet Explorer. Таким образом подразумевается, что работа с приложением будет вестись только через HTTP-протокол.
Структура интерфейса электронной доски объявлений должна быть понятна для обычного пользователя, в то же время необходимо позаботиться об наборе функциональных средств, обеспечивающих удобство работы с набором объявлений. Для этого разделим все объявления на рубрики и организуем их отображение в виде логического дерева разделов и подразделов каталога. Поскольку у каждого объявления есть определенный тип («спрос», «предложение», «обмен» и т.п.), нужно позаботиться о том чтобы пользователь мог просматривать объявления только нужного ему типа.
В целях обеспечения порядка и безопасности объявления могут добавлять только зарегистрированные пользователи. При регистрации у пользователя запрашивается логин, пароль и контактная информация. Для того чтобы исключить хранение паролей пользователей в базе данных в открытом виде, нужно предусмотреть их шифрование.
Зарегистрированные пользователи проходят процедуру авторизации, в которой у них запрашивается логин и пароль. Так как используется протокол HTTP, все отправляемые данные идут от пользователя к серверу в открытом виде. Для того чтобы свести к минимуму риск от перехвата пароля, после процедуры авторизации он ни в каком виде не должен передаваться от сервера к пользователю и наоборот. В тоже время нужно обеспечить дальнейшую аутентификацию пользователей для определения прав доступа при попытке выполнении ими определенных операций с данными. Следовательно, необходимо разработать такой алгоритм аутентификации, при котором между сервером и пользователем передается всего лишь некоторая ссылка-указатель на список успешно авторизированных пользователей. После завершения работы с приложением пользователь посылает команду на удаление себя из этого списка, и ссылка утрачивает свое значение. В случае если пользователь забыл послать команду на удаление, ссылка должна удаляться автоматически по истечению некоторого промежутка времени. Желательно, чтобы подобный указатель состоял из случайного набора большого числа символов, тогда шанс перебрать все ссылки на авторизированных на данный момент времени пользователей стремится к нулю.
Таким образом, возникает понятие «сессии пользователя» - при успешной авторизации на данного пользователя открывается так называемая сессия, которая фактически является записью в вышеупомянутом списке, пользователю средствами языка программирования сообщается только указатель на эту запись. При выполнении каких-либо операций с данными пользователь «возвращает» этот указатель приложению, которое сначала проверяет, есть ли у пользователя по полученному указателю открытая сессия и только потом выполняет требуемые действия.
Каждому зарегистрированному пользователю выделяется свой личный аккаунт, из которого он может добавлять, удалять и редактировать уже отправленные объявления, а также подписываться на почтовую рассылку новых объявлений.
Подписка на почтовую рассылку должна проходить по общепринятым правилам с подтверждением активирующего кода, то есть должна быть защищена от злоумышленников, пытающихся подписать чей-либо чужой почтовый ящик.
Необходимо предусмотреть режим администрирования с возможностью редактирования основных параметров электронной доски объявлений, таких как название, число объявлений, отображаемых на одной странице, включение или выключение почтовой рассылки.
Администратор может создавать и удалять разделы и подразделы каталога доски объявлений, просматривать список зарегистрированных пользователей, а так же удалять пользователей.
Режим модерирования предназначен для удаления любого объявления из каталога. Любой зарегистрированный пользователь может являться модератором доски объявлений, если администратор наделит его соответствующими правами доступа.
2. Разработка схемы данных
Для хранения данных в разрабатываемом приложении используется БД MySQL, формат данных которой принято представлять в табличной форме. Структурную схему базы данных электронной доски объявлений можно представить в виде набора из восьми таблиц, информация в каждой из которых группируется по смысловому и функциональному назначению и хранится в различных полях. Таким образом, приложение с помощью SQL-запросов обращается к БД только к нужным таблицам и полям и затем выполняет различные операции с полученными данными. Благодаря такому механизму достигается увеличение скорости обмена данными между приложением и БД.
По типу и функциональному назначению все таблицы проекта можно разделить на:
1) Статические таблицы - предназначены для хранения основных параметров электронной доски объявлений и типов объявлений. Число записей в этих таблицах в процессе работы приложения не меняется, первоначальные значения полей заносятся при инсталляции
2) Динамические таблицы – используются для хранения информации о разделах и подразделах каталога, пользователях и их правах доступа. Так же сюда следует отнести таблицы, в которых хранятся объявления и данные о почтовой рассылке и таблицу сессий, используемую для авторизации пользователей. Число записей во всех вышеперечисленных таблицах меняется динамически во время работы программы, что накладывает дополнительные требования на общий размер предоставляемой БД.
Рассмотрим назначение и структуру таблиц, используемых в проекте:
1. Таблица OPTIONS.
Статическая таблица, предназначена для хранения основных параметров электронной доски объявлений, состоит из трёх полей:
id |
name |
value |
id – порядковым номер записи, тип поля smallint (допустимое значение до 32767), ключевое.
name – название параметра, тип поля text (до 65535 символов)
value – значение параметра, тип text.
В данной версии проекта в таблице содержится шесть записей, которые заносятся при инсталляции. Содержание записей поля name: название BBS, число отображаемых на одной странице объявлений, максимальное время жизни объявления, рассылка объявлений по почте, удаление объявлений по истечению времени жизни, максимальный размер объявления.
При необходимости администратор может изменить любое из первоначальных значений поля value.
2. Таблица ACTION.
Статическая таблица, содержит тип объявлений, состоит всего из двух полей:
id |
action |
id – порядковым номер записи, тип поля smallint, ключевое.
action – название типа объявления, тип поля text.
Содержание записей поля action: предложение, спрос, обмен, аренда, прочее. Значения полей задаются автоматически в процессе инсталляции и в последующем времени не изменяются.
3. Таблица SUBJECT.
Предназначена для хранения индекса основного каталога (содержит информацию о структуре разделов и подразделов, образующих каталог).
id |
topic |
name |
id – идентификатор раздела или подраздела, тип поля int (значение до 2 147 483 647), ключевое. Для того чтобы данный идентификатор был уникальным (с неповторяющимися значениями), полю назначен дополнительный тип auto_increment. При первоначальном создании таблицы значение этого поля равно единице, при добавлении новой записи его значение автоматически инкрементируется. Поскольку удаление записей из таблицы не влияет на значение этого счётчика, мы получаем уникальность идентификатора записи. Для оптимизации поиска по таблице устанавливаем тип поля index.
topic – значение идентификатора раздела каталога, тип поля int, ключевое. Если данная запись описывает не подраздел, а корневой раздел каталога, то значение поля равно 0.
name – название раздела или подраздела каталога, тип поля text.
Поскольку администратор каталога может добавлять и удалять разделы и подразделы, число записей в этой таблице непостоянно.
4. Таблица USERS.
Содержит информацию о зарегистрированных пользователях.
id |
login |
password |
contact |
access |
id – идентификатор пользователя, тип поля int, ключевое, auto_increment, index.
login – логин пользователя, тип поля text.
password – 32-х символьный хэш-код пароля пользователя, тип поля text.
contact – контактная информация пользователя, тип поля text.
access – права доступа, тип поля smallint. 0 - администратор, 1 – пользователь, 2 – модератор.
5. Таблица MESSAGES.
Предназначена для хранения текста объявлений и их параметров, заданных отправителем.
id |
topic_id |
user_id |
action_id |
time |
time_live |
text |
id – идентификатор объявления, тип поля int, ключевое, auto_increment, index.
topic_id – значение идентификатора подраздела каталога, тип поля int, index.
user_id – значение идентификатора отправителя (пользователя), тип поля int.
action_id – значение идентификатора типа объявления, тип поля smallint.
time – дата написания объявления, тип поля text.
time_live – время удаления объявления в UNIX-формате, тип поля bigint.
text – текст объявления, тип поля text.
6. Таблица MAIL.
Содержит адреса и параметры, использующиеся для почтовой рассылки объявлений.
id |
user_id |
|
activation |
time |
id – идентификатор записи, тип поля int, ключевое, auto_increment, index.
user_id – значение идентификатора отправителя (пользователя), тип поля int.
email – почтовый адрес подписчика на рассылку, тип поля text.
activation – код для активации, тип поля text. После подтверждения активации значение поля равно 1. При временном выключении рассылки значение поля 0.
time – содержит значение времени в UNIX-формате, по истечению которого не активированная запись будет автоматически удалена из таблицы, тип поля bigint.
7. Таблица MAILSUB.
Описывает связь между подразделами и адресами подписчиков, которая используется для почтовой рассылки объявлений.
mail_id |
topic_id |
mail_id – значение идентификатора записи подписчика в таблице MAIL, тип поля int, index.
topic_id – значение идентификатора подраздела, на который оформлена подписка, тип поля int, index.
8. Таблица SESSIONS.
Содержит значения идентификаторов сессий авторизованных пользователей, используется для реализации механизма безопасной аутентификации.
user_id |
sid |
time |
user_id – значение идентификатора пользователя в таблице USERS, тип поля int.
sid – идентификатор сессии авторизованного пользователя, тип поля text.
time – значение времени в UNIX-формате, по истечению которого не продленная сессия будет автоматически удалена из таблицы, тип поля bigint.
Связи между полями таблиц приведены на рис. 2.1 структурной схемы данных. Ключевые поля-идентификаторы помечены знаком “*”, типы используемых связей: “один ко многим” и “один к одному”.
Рис. 2.1 - Схема данных
3. Разработка схемы программы
Рассмотрим основные задачи и требования, предъявляемые к разрабатываемому приложению на уровне организации WEB-интерфейса:
1) интерфейс отображение разделов каталога и объявлений,
2) интерфейс аккаунта пользователя,
3) интерфейс аккаунта модератора,
4) интерфейс аккаунта администратора,
5) интерфейс подписки на почтовую рассылку,
6) интерфейс авторизации и регистрации пользователей.
На функциональном уровне:
1) первоначальная инсталляция приложения на сервере,
2) соединение с БД MySQL,
3) инициализация основных параметров каталога,
4) проверка на корректность значений переменных, принимаемых от пользователя,
5) вывод разделов и подразделов каталога, а также объявлений,
6) регистрация новых пользователей,
7) авторизация пользователей,
8) аутентификация пользователей с помощью механизма сессий и проверка прав доступа,
9) добавление, редактирование и удаление объявлений,
10) организация механизма почтовой подписки с запросом подтверждающего кода,
11) подписка на подразделы каталога, активация, деактивация и удаление адреса из рассылки,
12) рассылка объявлений на почтовые адреса подписчиков,
13) редактирование основных параметров приложения,
14) добавление и удаление пользователей,
15) установка и снятие прав доступа с пользователей,
16) автоматическое удаление объявлений по истечению срока жизни, удаление не продлённых пользовательских сессий, удаление не активированных адресов почтовой рассылки.
На рис. 3.1 показана общая схема приложения и взаимодействие между его основными частями.
Рис. 3.1 - Функциональная структура программы
Таким образом, проект целесообразно реализовать в виде нескольких функциональных модулей, каждый из которых будет выполнять определённую задачу:
1) модуль инсталляции (с отображением интерфейса),
2) модуль соединения с БД MySQL,
3) модуль отображения разделов каталога и объявлений (с отображением интерфейса),
4) модуль регистрации новых пользователей (с отображением интерфейса),
5) модуль авторизации пользователей (с отображением интерфейса),
6) модуль аутентификации пользователей, основанном на механизме сессий,
7) модуль реализации аккаунта пользователя (с отображением интерфейса),
8) модуль реализации аккаунта администратора (с отображением интерфейса),
9) модуль реализации аккаунта модератора (с отображением интерфейса),
10) модуль реализации аккаунта подписки на почтовую рассылку (с отображением интерфейса).
4. Разработка алгоритмов
1) Алгоритм инсталляции.
Инсталляция подразумевает первоначальную установку приложения на интернет-сервер и создание аккаунта администратора. После инсталляции администратор переходит в свой аккаунт и добавляет разделы и подразделы в основной каталог.
Модуль-инсталлятор выполняет следующие действия:
а) создает новую БД или удаляет все таблицы в текущей БД, использующиеся приложением, если они уже были созданы;
в) создает таблицы с указанием всех необходимых полей и типов;
г) добавляет записи со значением базовых параметров в статические таблицы ACTION и OPTIONS.
г) запрашивает логин и пароль администратора, добавляет запись в таблицу USERS и установить права администратора.
2) Алгоритм отображения разделов и подразделов.
Для отображения списка разделов необходимо послать запрос на получение всех значений поля name из таблицы SUBJECT, где значение идентификатора раздела каталога topic = 0, и вывести результат на экран.
Для отображения списка подразделов используется точно такой же метод, только значение идентификатора раздела каталога topic сравнивается с текущим идентификатором раздела.
Для того чтобы записи сортировались в алфавитном порядке, все запросы дополняются директивой «ORDER BY name ASC». Если в текущем подразделе каталога присутствуют объявления нескольких типов, выводится вспомогательный список-фильтр с перечислением найденных типов, тогда пользователь может выбирать тот или иной тип объявлений, который должен выводиться на всех разделах и подразделах каталога.
3) Алгоритм отображения объявлений с применением фильтра на тип объявлений.
Для отображения объявлений берутся все значения полей таблицы MESSAGES, в которой значение поля topic_id совпадает со значением текущего идентификатора раздела каталога. Поскольку при отображении объявлений необходимо выводить ещё и контактную информацию об отправителе, а также тип объявления, в запрос вводятся дополнительные условия: значение поля user_id таблицы MESSAGES должно совпадать со значением идентификатора пользователя id таблицы USERS, а значение поля action_id – со значением поля id таблицы перечисления типов объявлений ACTION. Если пользователь применил фильтр на тип объявлений, запрос дополняется ещё одним условием: значение поля action_id должно соответствовать значению фильтра. Сортировка записей производится по полю id в порядке убывания, в результате чего вверху WEB-страницы каталога отображаются последние добавленные объявления.
4) Алгоритм ограничения числа объявлений, выводимых на одной WEB-странице.
Поскольку число объявлений, удовлетворяющих вышеприведённому запросу может быть слишком велико, для того чтобы не перегружать выводимые WEB-страницы используется алгоритм ограничения числа объявлений и формирование так называемой линейки – ссылок на страницы, содержащие результаты запроса. Для этого с помощью директивы COUNT предварительно подсчитывается количество строк в результирующем запросе, причём приложение запрашивает у БД именно число строк в нужном запросе, а не результат запроса, тем самым экономя время обмена данными и трафик (в случае если БД находится на другом удалённом сервере). По полученному значению определяется, нужно ли формировать линейку или нет. Если нужно, запрос дополняется директивой LIMIT с перечислением диапазона выводимых значений в результирующем запросе. Диапазон представляет собой некоторое начальное значение указателя на «окно» и максимальный размер этого «окна». Таким образом, результат запроса делится на «окна» и не перегружает выводимые страницы. Пользователь может выбирать для просмотра то или иное «окно», при этом само содержание запроса не изменяется, меняются лишь границы диапазона.
5) Алгоритм передачи значения фильтра при переходах по ссылкам каталога.
Включив фильтр на тип объявлений, пользователь может перейти с текущей страницы каталога на какую-либо другую, причём во время таких переходов приложение должно «знать», что фильтр был включен. Самый оптимальный способ для сохранения значения фильтра в случае программирования на языке PHP – это использование механизма сессий.
6) Алгоритм регистрации новых пользователей.
Регистрация пользователя происходит в следующей последовательности: на запрос программы пользователь вводит логин, пароль и контактную информацию о себе или об организации, которую он представляет на доске объявлений. Для удобства работы администратора со списком логинов пользователей проводится проверка на допустимый набор символов, состоящий только из английских букв и цифр. Для того чтобы исключить регистрацию пользователей с одинаковыми логинами, необходимо сделать проверку по полю login таблицы USERS. После вышеперечисленных проверок вычисляется хэш-код пароля пользователя. Хэш-код представляет собой 32-х символьную последовательность, вычисленную по алгоритму «MD5 Message-Digest Algorithm» (разработка корпорации RSA Data Security, [3]). Полученная последовательность является уникальной для символьной строки пароля пользователя, т.е. вероятность того, что два одинаковых пароля дадут одинаковый хэш-код, стремится к нулю. Основное преимущество кодирования по алгоритму MD5 – это невозможность обратного восстановления первоначальной символьной строки (пароля) по полученному хэш-коду. Вся полученная информация добавляется в поля login и password таблицы USERS, значение поля access устанавливается равным 1, что означает «права доступа на уровне пользователя».
7) Алгоритм авторизации пользователей.
Пользователю выводится форма для запроса логина и пароля, после ввода значений вычисляется хэш-код пароля и посылается запрос к таблице USERS. Если у пользователя есть учётная запись, соответствующая этим значениям, то он считается авторизованным. Прочитав значение поля id, мы получим идентификатор пользователя. Затем необходимо позаботиться об информации для модуля аутентификации, для этого используется таблица сессий SESSION. Поле user_id этой таблицы содержит значения идентификаторов пользователей с открытыми сессиями. Поскольку на один и тот же логин может быть открыта только одна сессия, сначала из таблицы удаляется запись с полученным ранее значением идентификатором авторизованного пользователя. Далее случайным образом генерируется 20-символьная строка, которую обозначим как «код сессии авторизованного пользователя». Именно эта строка, а не хэш-код пароля пользователя (или тем более его истинный пароль) впоследствии будет передаваться между приложением на сервере и браузером клиента. Код сессии заносится в поле sid. В целях безопасности, для того чтобы открытые сессии имели ограниченный во времени срок действия, каждой сессии назначается время жизни time, равное текущему значению времени на сервере плюс 60 минут. В случае, если пользователь ввёл ошибочные данные и его учётная запись не была обнаружена, ему предлагается либо заново пройти процедуру авторизации, либо зарегистрировать новую учётную запись.
8) Алгоритм аутентификации пользователей.
Обращение к данным идёт через запросы к таблице сессий SESSIONS и таблице пользователей USERS. Сначала идёт попытка считать 20-х символьный хэш-код сессии авторизованного пользователя, передаваемый между приложением и авторизованным клиентом. Затем из таблицы SESSIONS удаляются все сессии с просроченным временем жизни, если таковые имеются. Для этого текущее значение времени на сервере сравнивается со значением поля time.
Из таблицы SESSIONS получаем значение id той записи, у которой значение sid совпадает с хэш-кодом сессии авторизованного пользователя, после чего из таблицы USERS выбирается учётная запись с полученным идентификатором пользователя id. Эта учётная запись содержит идентификатор пользователя, логин, контактную информацию и права доступа, которая в дальнейшем используется различными модулями, требующими аутентификацию.
Далее продлевается срок жизни сессии: обновляется значение поля time.
В том случае, если 20-х символьный хэш-код сессии авторизованного пользователя считать не удалось, или такая сессия была не найдена в таблице SESSIONS, то аутентификация не возможна и пользователь считается неавторизованным.
Если пользователь закрывает сессию самостоятельно, происходит немедленное удаление записи из таблицы SESSIONS.
9) Алгоритм добавления новых объявлений.
Сначала идёт проверка максимально допустимой длины объявления, значение которой хранится в одной из записи таблицы OPTIONS. Объявления короче пяти символов также считаются недопустимыми. Поскольку сообщение может содержать недопустимые HTML-тэги, происходит замена таких тэгов на их «безопасные» эквиваленты.
Из таблицы MESSAGES удаляются сообщения, у которых истёк срок жизни, затем добавляется новая запись со значением полей topic_id, равному идентификатору текущего подраздела каталога доски объявлений в таблице SUBJECT; user_id, указывающим на идентификатор пользователя, отправившего объявление в таблице USERS; action_id, указывающим на идентификатор типа сообщения в таблице ACTION; time, равный значению текущей даты; time_live, обозначающим срок жизни объявления, и text, содержащий текст самого объявления.
В случае невыполнения условий проверок объявление в БД не заносится.
10) Алгоритм реализации механизма подписки на почтовую рассылку с запросом подтверждающего кода.
У авторизованного пользователя запрашивается почтовый адрес, причём происходит проверка на синтаксис (наличие знака «@» и «.»). Если в таблице MAIL в поле user_id уже содержится идентификатор данного пользователя и значение поля activation не равно «1» или «0», что указывает на то что рассылка на этот адрес находится в процессе подтверждения, выводится соответствующее сообщение и форма запроса подтверждающего кода, процесс регистрации прерывается (если значение поля activation равно «1» или «0», что указывает на то что у пользователя уже есть активированный почтовый адрес, процесс регистрации прерывается без вывода каких-либо форм). Иначе случайным образом генерируется число, которое заносится в таблицу MAIL поля activation. Это же число высылается на указанный почтовый адрес. В поле time заносится срок жизни записи, по истечению которого неподтвержденная рассылка будет удалена из таблицы.
При подтверждении рассылки, код, вводимый пользователем в форму запроса сравнивается со значением поля activation, в случае совпадения это значение заменяется на «1», что означает активацию рассылки. Пользователь может временно приостановить рассылку, при этом значение поля устанавливается в «0».
11) Алгоритм управления подпиской на подразделы каталога доски объявлений.
В поля mail_id и topic_id таблицы MAILSUB новой записи заносятся соответствующие значения идентификатора записи подписчика в таблице MAIL, а также подраздела каталога, на который оформляется подписка. В случае если подписка уже оформлена, новая запись не создаётся. Если пользователь хочет отписаться от какого-либо подраздела, запись удаляется.
12) Алгоритм почтовой рассылки объявлений.
Для того чтобы получить список почтовых адресов, на которые оформлена почтовая рассылка для текущего подраздела каталога доски объявлений, нужно из таблицы MAIL выбрать значения поля email тех записей, в которых значение поля id совпадает со значением поля mail_id таблицы MAILSUB и значение поля topic_id равно идентификатору текущего подраздела каталога. При этом значение поля activation таблицы MAIL должно быть равно «1».
По полученному списку организуется цикл, в котором на каждый адрес отправляется текст объявления.
Блок-схемы основных алгоритмов приведены на рисунке 4.1.
Рис. 4.1 - Блок-схемы алгоритмов регистрации и авторизации
5. Программная реализация
Для реализации проекта был выбран широко распространенный на сегодняшний день язык PHP – язык описания сценариев, которые встраиваются непосредственно в гипертекстовые HTML-файлы и исполняются на Web-сервере, что в значительной степени упрощает написание готовых проектов, сокращает время разработки структуры визуального отображения выводимой информации. Программа на PHP заключается в теги <?, ?>, а интерпретатор обрабатывает команды между этой парой тегов и формирует окончательный результат, передающийся на локальную машину. Самая значимая возможность языка РНР по сравнению с другими языками, например, Perl, - высокий уровень интеграции с базами данных. Создание и отладка PHP-скриптов значительно проще, чем отладка и создание скриптов на других языках. Язык скриптов напоминает своим синтаксисом язык C. PHP предназначен для платформ Win32, Linux и представляет собой отдельную CGI-программу, которая используется в качестве модуля к Web-серверау под управлением IIS или Apache. В настоящее время выпущена четвертая версия PHP с улучшенными производительностью и возможностями, именно эта версия языка (PHP 4.3.0) была выбрана автором данного проекта в процессе написания и тестирования программы, хотя написанные модули будут полностью совместимы и с предыдущей третьей версией PHP.
PHP поддерживает множество реляционных баз данных, в том числе Informix, Oracle, Sybase и др. Тем не менее немало скриптов на PHP используют сравнительно небольшую и компактную СУБД MySQL, совместимую со стандартом ANSI SQL и обеспечивающую высокую производительность. MySQL является реляционной СУБД и в SQL-запросах позволяет связывать таблицы по общим полям, поддерживает индексы, автоинкрементные поля, а также множество функций для преобразования данных. К MySQL разработаны самые разнообразные надстройки, предоставляющие графический или Web-интерфейс для манипуляции данными - создания таблиц, добавления и редактирования в них записей, отбора нужных строк. Например, с помощью системы phpMyAdmin, написанной целиком на PHP, можно подготовить структуру таблиц, ввести начальные значения вручную или из текстового файла и проверить работоспособность SQL-запросов, использующихся в проекте.
Учитывая то, что существует множество провайдеров, предоставляющих хостинг со связкой PHP/MySQL, выбранный набор программных средств способствует практическому воплощению готового проекта в жизнь.
Работа с базой данных
Последовательность подключения к базе данных и управления табличными данными традиционна – сначала устанавливается связь, потом выдается запрос и обрабатывается результат. Для подключения к базе данных нужны три параметра: имя хост-узла, имя пользователя и пароль. Определив эти параметры, можно установить соединение с БД при помощи функции MYSQL_CONNECT(), затем функцией MYSQL_SELECT_DB() выбирается нужная база данных (см. Приложение А). В случае ошибки соединения или выбора БД выводится соответствующее сообщение.
Для получения данных используется функция MYSQL_QUERY(), в которой указывается необходимый SQL-запрос, передаваемый MySQL.
Получить значения отдельных полей позволяет функция MYSQL_FETCH_ARRAY(), которая возвращает ассоциативный массив с данными (см. Приложение B).
Для получения количества строк в результате запроса служит функция MYSQL_NUM_ROWS(), которая используется для определения наличия в таблице той или иной записи (например, учетной записи пользователя).
Составление SQL-запросов
Чтобы начать работу с MySQL прежде всего требуется создать базу данных, с которой мы будем взаимодействовать. Это делается запросом “CREATE database имя_БД”.
Для создания таблицы используется запрос “CREATE table имя_таблицы” с перечислением полей и их типов (см. Приложение В). Для добавления новой записи в таблицу – “INSERT INTO имя_таблицы VALUES (перечисление_значений)”, для вывода данных “SELECT перечисление_полей FROM имя_таблицы WHERE условие ”.
Важной особенностью является возможность дополнения запросов следующими функциональными директивами: лимит выдаваемых строк “LIMIT”, сортировка данных в порядке убывания/возрастания значения поля “ORDER BY название_поля DESC/ASC”, подсчёт строк в запросе “COUNT (*)”.
Для редактирования значения поля используется запрос “UPDATE имя_таблицы SET имя_поля = значение поля WHERE условие”, для удаления “DELETE FROM имя_таблицы WHERE условие”. Практическая реализация вышеперечисленных запросов в коде приведена в Приложении.
Обработка данных, полученных от пользователя
Для проверки строк данных, полученных от пользователя на допустимые значения символов, используется функция ereg() и составленное соответствующим образом регулярное выражение, которым проверяется строка, передаваемая этой функции. Например, регулярное выражение “[^0-9]” эквивалентно по смыслу фразе “проверка на наличие в строке цифровых символов”. Регулярными выражениями проверяются все цифровые значения переменных, а так же строковые переменные логина, пароля и e-mail’а.
Шифрование паролей, вычисление хэш-кода символьной строки
Существует множество способов зашифровать или вычислить хэш-код какой-либо символьной строки, язык PHP предоставляет для этого целый набор функций (crypt, crc32 и др.). Поскольку мы уже ранее определились с алгоритмом MD5, будем использовать функцию md5().
Передача значений переменных между сервером к клиентом
При используемом в проекте алгоритме аутентификации необходима возможность многократной передачи значения кода сессии авторизованного пользователя между сервером (программой) и клиентом (браузером). Суть проблемы в том, чтобы отвести в определенной области памяти (на сервере или у клиента) место, где было бы возможно сохранять значение этого кода, причем это значение хранилось бы в течение требуемого периода времени. Для этой цели изобретен механизм Cookies и механизм сессий. Cookies подразумевает сохранение значений переменных на стороне клиента, механизм сессий – на стороне сервера. Для нашей задачи пригодны оба метода, но у первого есть большой недостаток, проявляющийся на практике – он заключается в том, что многие пользователи целенаправленно отключают этот режим в браузерах, в таком случае передача значений переменных становится невозможной. Сессии лишены этого недостатка, и, поскольку язык PHP предоставляет набор удобных функций для работы с сессиями, будем использовать именно этот механизм. Для начала нужно запустить сессию функцией session_start(), после чего можно устанавливать и считывать значения любых переменных: “$_SESSION["имя_переменной"] = значение_переменной”.
Особенность метода состоит в том, что PHP все же использует Cookies на стороне клиента, чтобы сохранить там значение идентификатора обратившегося к скрипту пользователя (PHPSID). Именно через этот идентификатор сервер «узнает», в какой области памяти он сохранил переменные. Однако, если у клиента выключены Cookies, PHP самостоятельно внедряет в отображаемый гипертекст дополнение ко всем ссылкам перехода строки вида
PHPSID=идентификатор_сессии, то есть при переходе пользователя по этим ссылкам значение идентификатора всё равно передается серверу и значения сохраненных переменных потеряны не будет. Именно это достоинство сессий обеспечило их повсеместное применение на средних и крупных проектах, написанных на языке PHP.
Отправка текста объявлений на потовые адреса подписчиков
Для отправки текста на e-mail в PHP служит функция mail(), в которой указывается почтовый адрес, тема сообщения и его тело. Почтовый адрес необходимо проверять на правильность синтаксиса, иначе высока вероятность взлома приложения путём ввода серверных команд удаленного доступа. Синтаксис проверяется регулярным выражением (см. Приложение J)
Формирование интерфейса
Формирование интерфейса происходит стандартным образом на языке гипертекстовой разметки HTML. Для увеличения скорости загрузки страниц каталога электронной доски объявлений весь дизайн интерфейса выполнен в текстовом виде. Автору удалось минимизировать HTML-код путем исключения избыточности (ненужных символов, HTML-тэгов, замена однотипных участков текста на вызов функции JavaScript, содержащий шаблон с этим текстом и т.п.), которая на сегодняшний день весьма распространена в Web-дизайне.
6. Описание программы
Разрабатываемое интернет-приложение предназначено для организации интерактивной многофункциональной электронной доски объявлений. Приложение устанавливается на сервере, поддерживающим выполнение PHP-скриптов не ниже третьей версии. Для работы приложения с данными необходима СУБД MySQL версии 3.23 или выше, которая в целях максимальной производительности должна быть установлена на том же сервере, что и интерпретатор языка PHP, однако это условие не является обязательным.
Для установки приложения необходимо по FTP-протоколу или любым другим образом скопировать файлы с поставляемого дистрибутива в каталог выделенного сервера, прописать название БД, логин и пароль для доступа (выдаются администратором интернет-сервера) в модуле tunes.php и запустить инсталлятор install.exe. После ввода регистрационной информации администратора электронная доска объявлений сразу же готова к работе.
Просмотр объявлений осуществляется через интуитивно-понятный WEB-интерфейс.
Для удобства пользователя, все объявления разделены на тематики, и содержатся в упорядоченном порядке в разделах каталога. Каждому объявлению соответствует тип – «спрос», «предложение», «обмен», «аренда», «прочее». Пользователь может включить фильтр на отображение объявлений только нужного ему типа.
Объявления могут добавлять только зарегистрированные пользователи. При регистрации у пользователя запрашивается логин, пароль и контактная информация. После регистрации пользователь может работать в своем аккаунте, добавлять, удалять и редактировать уже отправленные объявления, а также подписываться на почтовую рассылку новых объявлений.
Механизм подписки на почтовую рассылку имеет простой и удобный интерфейс, защищен от злоумышленников, пытающихся подписать чей-либо чужой почтовый ящик. Каждое добавленное объявление рассылается на почтовые адреса подписчиков без каких-либо искусственных ограничений и временных задержек, тем самым обеспечивая эффективность информирования.
Предусмотрен режим администрирования с возможностью редактирования основных параметров электронной доски объявлений, таких как название, число объявлений, отображаемых на одной странице, включение или выключение почтовой рассылки.
Администратор может создавать и удалять разделы и подразделы каталога доски объявлений, просматривать список зарегистрированных пользователей, а так же удалять пользователей.
Режим модерирования предназначен для удаления любого объявления из каталога. Любой зарегистрированный пользователь может являться модератором доски объявлений, если администратор наделит его соответствующими правами доступа.
Авторизация пользователей имеет простой интерфейс и основана на безопасном алгоритме аутентификации, который обеспечивает надежную защиту от взлома паролей пользователей для приложений подобного уровня.
7. Руководство программиста
Проект состоит из 10 модулей, ниже будет описан каждый из них, а также функции, которые в них используются.
1) Модуль install.php
Назначение: для первоначального создания базы данных и таблиц, необходимых для работы приложения.
Принимаемые параметры:
action – код действия (0 – вывод формы запроса логина и пароля администратора, 1 – инсталляция); login – логин администратора; password – пароль администратора.
Функции:
ok($sql,$table);
- вывод в сообщения в гипертекстовом формате о результате выполнения запроса sql в таблице table.
2) Модуль tunes.php
Назначение: содержит константы со значениями логина, пароля и имени базы данных, использующиеся для подключения к БД MySQL:
dbName – имя базы данных; hostname – имя хоста MySQL или URL удаленной базы данных; username – логин пользователя; password – пароль для доступа к БД.
3) Модуль index.php
Назначение: отображение в гипертекстовом формате подразделов и разделов каталога и объявлений с разделением на страницы.
Принимаемые параметры:
action – код действия (0 – отображение главной страницы каталога, 1 – отображение разделов каталога, 2 – отображение объявлений в текущем подразделе каталога); id – идентификатор текущего раздела или подраздела каталога; f – идентификатор фильтра сообщений (0 – фильтр выключен, 1..3 – фильтр включен на соответствующий тип; n – порядковый номер запрашиваемой страницы.
Функции:
check($value);
- возвращает 1 если строка value содержит цифровые символы, иначе 0.
catalog_options($id);
- возвращает значение параметра каталога с порядковым номером id из таблицы OPTIONS.
catalog_item_name($id);
- возвращает значение поля name из таблицы SUBJECT по заданному идентификатору подраздела id.
catalog_print();
- выводит в гипертекстовом формате дерево подразделов и разделов каталога.
message();
- выводит в гипертекстовом формате объявления текущего раздела или подраздела с применением фильтра типа сообщений.
message_catalog();
- выводит в гипертекстовом формате отображение разделов и подразделов каталога, отображаемые на заглавной странице электронной доски объявлений.
4) Модуль adduser.php
Назначение: добавление новой учетной записи пользователя.
Принимаемые параметры:
action – код действия (0 – вывод формы регистрации, 1 – добавление учетной записи); login – желаемый логин пользователя, password – желаемый пароль, contact – контактная информация о пользователе.
Функции:
check($value);
- возвращает «1» если строка value содержит цифровые символы, иначе «0».
check_enter($value)
- возвращает «1» если строка value содержит буквенно-цифровые символы, иначе «0».
check_id($id);
- возвращает значение поля topic таблицы SUBJECT по заданному порядковому номеру записи.
message_check($t);
- возвращает текст t, в котором HTML-тэги заменены на их «безопасные» эквиваленты.
user_form_add();
- выводит форму регистрации пользователя.
user_add();
- добавляет новую учетную запись пользователя в таблицу USERS.
5) Модуль enter.php
Назначение: авторизация пользователя.
Принимаемые параметры:
login – логин пользователя, password – пароль.
Функции:
check_enter($value);
- возвращает «1» если строка value содержит буквенно-цифровые символы, иначе «0».
randString($pass_len);
- возвращает строку длиной pass_len из случайно сгенерированных буквенно-цифровых символов.
6) Модуль sessions.php
Назначение: аутентификация пользователя.
Принимаемые параметры:
$_SESSION["session"] – значение кода сессии авторизованного пользователя.
Функции:
not_enter();
- делает редирект пользователя на модуль авторизации enter.php в случае невозможности аутентификации.
7) Модуль users.php
Назначение: отображение в гипертекстовом формате интерфейса аккаунта пользователя и функциональный набор средств для работы с объявлениями.
Принимаемые параметры: action – код действия, $id, $n, $i, $a;
Функции:
check($value);
- возвращает «1» если строка value содержит цифровые символы, иначе «0».
check_enter($value)
- возвращает «1» если строка value содержит буквенно-цифровые символы, иначе «0».
check_id($id);
- возвращает значение поля topic таблицы SUBJECT по заданному порядковому номеру записи.
catalog_options($id);
- возвращает значение параметра каталога с порядковым номером id из таблицы OPTIONS.
catalog_item_name($id);
- возвращает значение поля name из таблицы SUBJECT по заданному идентификатору подраздела id.
user_login($id);
- возвращает логин пользователя из таблицы USERS по заданному идентификатору id.
catalog_print();
- выводит в гипертекстовом формате дерево подразделов и разделов каталога.
message();
- выводит список объявлений текущего раздела или подраздела каталога объявлений.
catalog_list();
- выводит список разделов и подразделов каталога объявлений.
action_list();
- формирует список типов объявлений из таблицы ACTION.
message_add();
- добавление нового объявления в таблицу MESSAGES.
message_check($t);
- возвращает текст t, в котором HTML-тэги заменены на их «безопасные» эквиваленты.
message_del();
- удаление объявления из таблицы MESSAGES.
message_form_edit();
- вывод формы редактирования текста объявления.
message_edit();
- обновление текста объявления в таблице MESSAGES.
user_exit();
- закрытие пользовательской сессии и выход из аккаунта.
user_del();
- удаление учетной записи текущего пользователя.
send_mail();
- рассылка объявлений на почтовые адреса подписчиков.
8) Модуль mail.php
Назначение: отображение в гипертекстовом формате интерфейса аккаунта подписки на почтовую рассылку и необходимый функциональный набор средств для работы.
Принимаемые параметры: action – код действия (1 – добавление подписки на текущий подраздел каталога, 2 – удаление подписки от текущего раздела, 3 – включение почтовой рассылки, 4 – удаление подписки, 5 – регистрация почтового адреса, 6 – активация рассылки подтверждающим кодом, 7 – удаление почтового адреса из рассылки); id – текущий подраздел каталога; еmail – почовый адрес подписчика.
Функции:
check($value);
- возвращает «1» если строка value содержит буквенно-цифровые символы, иначе «0».
check_id($id);
- возвращает значение поля topic таблицы SUBJECT по заданному порядковому номеру записи.
check_mail($mail);
- возвращает «1» если строка mail содержит правильный формат записи e-mail адресов, иначе «0».
catalog_options($id);
- возвращает значение параметра каталога с порядковым номером id из таблицы OPTIONS.
message_catalog();
- выводит в гипертекстовом формате отображение разделов и подразделов каталога, отображаемые на заглавной странице электронной доски объявлений.
topic_add();
- добавление подписки на почтовую рассылку объявлений текущего подраздела каталога.
topic_del();
- удаление подписки на почтовую рассылку объявлений текущего подраздела каталога.
sendmail_enable();
- включение или выключение рассылки на данный e-mail.
topic_del_all();
- отписка почтового адреса от всех подразделов.
user_reg();
- регистрация почтового адреса.
user_reg_activation();
- активация почтовой подписки.
user_form_reg();
- вывод формы регистрации почтового адреса.
activation_wait();
- вывод формы с запросом на ввод активирующего кода.
user_del();
- удаление почтового адреса из рассылки.
9) Модуль moderator.php
Назначение: отображение в гипертекстовом формате интерфейса аккаунта модератора и функциональный набор средств для работы с каталогом объявлений и удалением сообщений.
Принимаемые параметры:
action – код действия (0 – отображение главной страницы каталога, 1 – отображение разделов каталога, 2 – отображение объявлений в текущем подразделе каталога); id – идентификатор текущего раздела или подраздела каталога; n – порядковый номер запрашиваемой страницы.
Функции:
check($value);
- возвращает «1» если строка value содержит цифровые символы, иначе «0».
catalog_options($id);
- возвращает значение параметра каталога с порядковым номером id из таблицы OPTIONS.
catalog_item_name($id);
- возвращает значение поля name из таблицы SUBJECT по заданному идентификатору подраздела id.
catalog_print();
- выводит в гипертекстовом формате дерево подразделов и разделов каталога.
message();
- выводит в гипертекстовом формате объявления текущего раздела или подраздела.
10) Модуль admin.php
Назначение: отображение в гипертекстовом формате интерфейса аккаунта администратора и функциональный набор средств для работы с пользователями, основными параметрами и разделами каталога.
Принимаемые параметры:
action – код действия (1 – обновляет значение основных параметров каталога в таблице OPTIONS, 2 – создает новый раздел в каталоге с идентификатором id, 3 – создает новый подраздел с идентификатором id, 4 – удаляет раздел или подраздел с идентификатором id, 5 – удаляет пользователя с логином name, 6 – снимает права модерирования с логина name, 7 – назначает права модерирования на логин name, 8 – выводит список зарегистрированных пользователей в гипертекстовом формате)
Функции:
check($value);
- возвращает «1» если строка value содержит цифровые символы, иначе «0».
refresh();
- делает редирект пользователя на модуль admin.php.
8. Контрольный пример
Интерфейс приложения выглядит следующим образом:
Рис. 8.1 - Вывод разделов и подразделов основного каталога электронной доски объявлений
Рис. 8.2 - Вывод всех объявлений из раздела «Компьютеры»
Рис. 8.3 - Вывод объявлений с применением фильтра на тип «Предложение»
Рассмотрим процесс регистрации нового пользователя, например belka:
Рис. 8.4 - Регистрация нового пользователя belka
Содержимое таблицы пользователей USERS до регистрации:
Рис. 8.5 - Дамп данных таблицы USERS до регистрации
Содержимое таблицы после регистрации:
Рис. 8.6 - Дамп данных таблицы USERS после регистрации
Последняя строка в таблице содержит добавленную учетную запись:
идентификатор, хэш-код пароля, контактную информацию и права доступа пользователя.
Рассмотрим процесс авторизации зарегистрированного пользователя belka:
Рис. 8.7 - Авторизация пользователя
Содержимое таблицы сессий SESSIONS после авторизации пользователя:
Рис. 8.8 - Дамп данных таблицы SESSIONS
Запись в таблице содержит идентификатор пользователя, код и время жизни сессии.
После успешной аутентификации пользователь продолжает работу в своем аккаунте:
Рис. 8.9 - Аккаунт пользователя
Рассмотрим пример добавления нового объявления:
Рис. 8.10 - Добавление нового объявления: выбор подраздела каталога
Заключение
Задача, поставленная на бакалаврскую работу, была успешно выполнена. На примере электронной доски объявлений было разработано интерактивное интернет-приложение, сочетающее в себе работу с базой данных MySQL, практическую реализацию механизма регистрации, авторизации пользователей, основные принципы подписки на почтовую рассылку. Также в работе был разработан и применен алгоритм аутентификации, который обеспечивает надежную защиту от взлома паролей пользователей для приложений подобного уровня.
Взаимодействие приложения с пользователем было выполнено в виде простого и интуитивно-понятного WEB-интерфейса.
Данный проект функционирует в сети интернет по адресу http://members.lycos.co.uk/ngtubbs.
В качестве дальнейшего улучшения и расширения функциональности проекта можно отнести добавление режима предварительного модерирования сообщений, алгоритма защиты от прямого перебора паролей пользователей с помощью учета и блокирования IP-адресов, возможность ведения логов, скриптов отображения расширенной статистики, модуля резервного копирования данных.
Список литературы
1. Д.В. Котеров. Самоучитель PHP 4. Питер 2000 г.
2. Р. Курепин. Учебный курс по программированию на PHP.
3. Л. Ульман. Основы программирования на РНР.
4. PHP Manual.
5. M. Kabir. Secure PHP Development.