div.main {margin-left: 20pt; margin-right: 20pt}
Технологии чата
Сегодня я хочу сказать несколько слов об одной проблеме. На самом деле
этому вопросу можно посвятить целую книгу, а не одну статью, так что я коснусь
вопроса очень поверхностно, и основная моя цель — натолкнуть Вас на
собственные исследования в этой области. Надо сказать, что это не так уж и
сложно, как кажется на первый взгляд, и при определенных обстоятельствах есть
возможность сделать свой собственный чат, пользуясь только РНР, и даже без
поддержки баз данных. А эта статья — всего лишь маленький намек на те проблемы
и методы их решения, которые могут встретиться у Вас на пути.
Итак,
чат. Очень многие веб-мастера мечтают сделать для своих посетителей хороший
чат, но они даже не представляют всю сложность этой задачи. Как правило, такой
веб-мастер идет проторенным путем, ищет в Интернете исходники чатов и
размещает их у себя на сервере. Непременное условие — обязательное наличие на
сервере поддержки одного из языков программирования. Как правило, чаты
предпочитают делать на CGI (например, на языке Perl, но совсем не
обязательно), и такие чаты получаются достаточно быстрыми и надежными. Но как
быть тому, кто по ряду причин не может себе позволить запускать скрипты CGI на
своем сайте? Или не может до конца освоить один из языков программирования для
CGI? Или, если даже и освоил один из языков для CGI, просто не знает, как
подступиться к проблеме. Конечно, совсем без усилий тут не обойтись, ведь чат
— дело серьезное и требует к себе внимательного отношения. Нет, вообще-то
можно пойти и по легкому пути. Например, открыть свой чат на другом бесплатном
сервере. А что — преимуществ масса, ведь вся настройка сводится к выбору
цвета, расположению фреймов и другим мелким деталям... Но есть, как всегда, и
отрицательные стороны такого решения. Никто за просто так Вам не даст
пользоваться своим чатом — придется рассчитываться тем, что на Вашем чате
будут показываться неизвестно чьи баннеры. Да и прикрыть могут в любой момент.
Это единственный способ сделать чат тем, у кого хостинг не поддерживает CGI.
Опять же — отрицательный момент в том, что посетитель на самом деле уйдет с
Вашего сайта, а это тоже не есть хорошо. Однако, как всегда, есть способ
лучше! Если Вы располагаете поддержкой сервера CGI или РНР, Вы можете легко
найти в Интернете массу хороших и не очень скриптов чатов и разместить их у
себя на сайте, тогда Вы уже ни от кого не будете зависеть. Но есть недостатки
и у этого способа. Дело в том, что исходники таких чатов всегда общедоступны.
И у них почти всегда обнаруживается какая-нибудь уязвимость, позволяющая
злоумышленникам взламывать Ваш любимый чат. Не всегда такие взломы приносят
существенный вред, но все равно неприятно, что кто-то роется там, где доступа
никому нет. Итак, если Вы готовы воспользоваться уже написанным кем-то кодом
чата, будьте готовы к двум проблемам: предварительной настройке чата (это тоже
не так просто иногда) и к возможности взлома чата недоброжелателями через
стандартную ошибку, коими часто просто изобилуют бесплатные скрипты. Если
перечисленные вопросы очень важны для Вас, придется идти по трудному и
сложному пути — пути создания своего собственного чата. Для основного языка
программирования можно выбрать РНР, так как его поддержка наиболее часто
встречается на серверах в сети. Кроме того, исключительно из совместимости
можно поставить себе ряд условий — никаких баз данных (их ведь несколько, и
заранее не известно, что за база на сервере) и работоспособность на версии
РНР3. Это еще больше усложняет задачу, так как придется отказаться от сессий,
поддержка которых включена только в 4 версию РНР. Но именно это дает нам
возможность важной для нас сейчас совместимости, уж на 3 версии работают
сейчас все сервера в сети. Итак, я повторюсь — основная наша задача есть
работа чата на РНР версии 3 без баз данных. Что можно сделать, исходя из
поставленных условий? Очень многое на самом деле. Во-первых, нам придется
решать проблемы авторизации пользователей в чате. Предложенных решений масса,
но у каждого из них есть очень большой недостаток — знание того, как все
шифруется, неизбежно приводит к появлению алгоритмов расшифровки. Значит, нам
придется делать свой собственный алгоритм шифрования паролей пользователей с
условием невозможности расшифровки за разумный промежуток времени (надеюсь,
NASA или ФБР не будут ломать Ваш чат). Кроме того, неплохо сделать так, чтобы
даже при краже файла с паролями их невозможно было бы расшифровать. В моем
опыте есть случай, когда ошибка одного скрипта привела к появлению возможности
доступа к исходникам на сайте и к краже паролей. Правда, тут есть и большой
минус. Если человек забыл пароль, его нельзя уже восстановить, так как пароль
нигде не хранится незашифрованным. В этом случае можно удалять регистрационную
запись пользователя и предоставить ему возможность повторно
зарегистрироваться. В качестве альтернативной авторизации нужно использовать
почтовый ящик, который пользователь должен указать при регистрации. Если он не
указывается, ему же (пользователю) хуже, ведь установить точно, является ли он
действительно владельцем регистрационной записи с потерянным паролем, уже
нельзя. Если же ящик указан и указан правильно, на него следует отправить
запрос об удалении регистрационной записи, и при положительном ответе
регистрация снимается простым удалением строчки из файла с регистрационными
данными. Кстати, сам адрес электронной почты тоже можно шифровать, но уже
обратимым методом, в отличие от пароля. Хотя иногда это лишнее. Возможно,
покажется странным, что пароли будут шифроваться до такого состояния, что их
нельзя (мы уже условились, что нельзя — это значит нельзя за разумный
промежуток времени, а вообще-то можно все, только долго...) даже расшифровать.
Как же эти пароли будут проверяться на соответствие с хранимым в базе
зашифрованным паролем? Все очень просто и элегантно. Я опишу на примере
Windows 2000, где реализован примерно следующий алгоритм. При регистрации
пользователь вводит свой пароль, который обрабатывается специальной функцией
необратимого шифрования, и результат заносится в базу паролей вместе с
учетными записями (имя пользователя, описание и т.д.). Когда пользователь
входит в систему в следующий раз, Windows опять шифрует введенный пароль своей
стандартной функцией и сравнивает результат с тем, что хранится у нее в базе
данных паролей. Если результат шифрования введенного пароля и хранящегося в
базе есть идентичные строки, пользователь авторизован, если нет — ошибка ввода
пароля. Таким образом, достигается большая конфиденциальность, так как пароль
не хранится в открытом виде, а хранится уникальный идентификатор строки,
соответствующей паролю. И даже если база данных с хранимыми паролями будет
украдена, толку от этого похитителю будет мало, ведь открытых паролей там нет,
только зашифрованные. А обратной расшифровке такие идентификаторы просто не
поддаются — уж так устроена функция шифрования. Правда, есть подводный
камень и тут (ну как всегда!). Дело в том, что простые пароли очень легко
восстановить методом перебора. Пишется несложная программа, она перебирает
различные варианты (комбинации символов пароля), шифрует их и сравнивает
результат шифрования с тем, что хранится в украденной базе. Это называется
метод прямого перебора паролей. Есть даже, кстати, специальные словари для
подобных дел. Таким образом, очень легко взломать нестойкий пароль. О
стойкости пароля сказано уже очень много, но вкратце смысл таков — ни в коем
случае нельзя применять для пароля смысловое сочетание букв. Другими словами —
пароль должен казаться полной бессмыслицей постороннему человеку. Такой пароль
гораздо труднее подобрать методом прямого перебора и практически невозможно —
перебором слов по специальным словарям. Очень хорошо, если в пароле
присутствуют знаки препинания, чередуются маленькие и большие буквы,
используются цифры и т.д. — насколько хватит фантазии и собственной памяти.
Впрочем, я больше чем уверен, что большинство из Вас не пользуются данными
методиками для увеличения стойкости пароля, а значит, и нет смысла дальше
развивать эту тему, тем более что подобных рекомендаций очень много в
Интернете. Кроме авторизации, очень важным является пункт настройки чата.
Как правило, применяются несколько вариантов настройки. Самые распространенные
— настройка перед каждым входом в чат, настройка чата под себя один раз с
памятью на cookie и настройка чата в любой момент времени. На мой взгляд,
самым удобным является разумная комбинация всех трех вариантов. Если
пользователь так хочет, пусть так и будет, только не нужно забывать и о тех,
кому не очень хочется что-то там отстраивать и настраивать, а нужен вход в чат
одним кликом. Для таких посетителей необходимо предусмотреть загрузку
конфигурации чата по умолчанию. Еще лучше, кроме загрузки по умолчанию,
предусмотреть гостевой вход, где не потребуется даже регистрация. Сделать это
проще всего так — зарегистрировать самому ник c именем Гость, выбрав для
пароля, например, guest, и при входе без ввода учетных данных (ника и пароля)
загружать именно эту учетную запись. А остальным можно предоставить
возможность настраивать самые различные параметры: цвет фона, шрифт и его
размер, фразу для входа, время обновления окна чата, фильтр матов, отключение
графических иконок и т.д. Все это должно присутствовать в окне авторизации или
настраиваться из самого чата. Когда все необходимые параметры для входа в
чат настроены, посетитель должен обратить свое внимание на бросающуюся в глаза
кнопку или ссылку входа в чат. Как правило, все параметры настройки, введенные
Ник и пароль передаются методом POST в загрузчик, где после соответствующей
обработки в браузер загружаются несколько фреймов. Сделать чат без фреймов
теоретически можно, но это очень неудобно и непрактично, так что Вам просто
придется освоить фреймовую структуру. Она не очень сложна, но если что-то не
понятно, можно взять готовый файл загрузчика с другого чата и применить его у
себя. Как правило, чат состоит из 3-4 фреймов. Экран делится не несколько
частей по горизонтали и по вертикали. В горизонтально разделенных фреймах
выводят информацию о количестве посетителей в чате (или чаще их список) и
собственно саму текстовую и графическую (так называемые иконки — смайлики)
информацию, которой обмениваются посетители. В вертикально разделенных фреймах
можно обеспечить окно для ввода текста, выбор его вида, цвета и т.д. Там же
выбираются иконки, если они предусмотрены. Кроме того, тут можно выводить и
другую полезную информацию — реклама, ссылки, счетчики и т.д. Перед тем,
как фреймовая структура будет сформирована и передана браузеру, нужно
предусмотреть еще очень многое. Ну, про авторизацию уже я говорил, но именно
тут нужно вести учет входов (для показа тех, кто находится в данный момент в
чате), проверять соответствие дат и сохранять ежедневные логи разговоров, если
это нужно. Тут же надо проверять и корректировать все введенные пользователем
данные. Не рассчитывайте, что переменные, переданные Вашему загрузчику методом
POST, не смогут принять иное значение, чем Вы предусмотрели. Можно ведь
воспользоваться еще и методом GET, а это значит, что Вашему загрузчику могут
такое передать...! Приучите себя обрабатывать полученные переменные по всем
критериям. Другими словами — всегда проверяйте, соответствует ли полученная
переменная нужному диапазону, и если нет — лучше всего присвоить ей
стандартное значение. Кстати, очень неплохо воспользоваться контролем методов
передачи данных. Если Вы пользуетесь методом передачи данных POST, проверьте
переменную окружения $QUERY_STRING. Если она не пуста, Вашему загрузчику
пытаются что-то передать еще и по методу GET. Эти потуги можно пресекать. К
сожалению, кроме самого загрузчика фреймовой структуры, данные необходимо
передать в другие файлы чата. Если этого не сделать, все настройки чата будут
утеряны, а авторизация потеряет всякий смысл, так как любой желающий сохранит
Ваш загрузчик у себя на диске, подредактирует его, как надо, запустит... И
войдет в чат, минуя все входные процедуры. Как минимум, это дает возможность
ему быть невидимым в чате, как максимум — входить под любым ником, что,
согласитесь, неприятно. Чтобы такого не происходило, Вам придется немного
усложнить один или несколько фреймов, Точнее — программ, отвечающих за вывод
информации в фреймы. Каждому соответствует свой собственный файл, и в каждом,
соответственно, своя программа. Вот этим-то программам и нужно передать все
данные о пользователе, причем информацию о посетителе передать так, чтобы
нельзя было явно ее изменить. Информацию о цвете и настройках можно передать,
как обычно, методом GET. Она, как правило, не влияет на существенные настройки
чата и все равно доступна для изменения. Есть возможность передавать все
данные с помощью cookie (это такие небольшие файлы, которые сервер сохраняет
на компьютере пользователя), но метод этот плох тем, что посетитель без
поддержки cookie или с отключенной такой поддержкой в настройках браузера не
сможет пользоваться Вашим чатом. Хотя это самый легкий путь. Изменить файл
cookie на диске можно, но это уже несколько сложнее, и специалист такого
уровня вряд ли заинтересуется Вашим чатом. У него и так работы хватает:-).
Можно зашифровать информацию, записываемую в cookie, одним из методов
шифрования, поддающихся обратной расшифровке. Вариантов много! Но, как я уже
говорил, это иногда плохо, так как не максимально надежно и часто не
совместимо на 100%. Остается только передать пароль и информацию об
авторизованном пользователе тоже через метод GET. Кстати, если кто еще не
очень понимает, что это за методы передачи файлов, попробую вкратце объяснить.
Метод POST основан на передаче данных через форму (необязательно), а значит
требует перехода либо по кнопке, либо по ссылке, либо по графическому рисунку.
То есть, требуется реальное действие пользователя. Метод передачи данных GET
применяется тогда, когда надо передать информацию программе без активного
действия. Вот пример ссылки, передающей данные программе, расположенной в
файле index.phtml: http://myhost.by/index.phtml?temp=1&qwe= slovo. Как
видите, передаются и цифры, и символы, причем передать можно несколько
переменных за один раз. В результате обработки такой ссылки программа в
index.phtml получит две переменные — $temp и $qwe с соответствующими
значениями. Передавать таким методом учетные записи незашифрованными
нельзя, да это и не требуется. Я говорил о специальном цифровом идентификаторе
введенного пароля. На основе его, ника пользователя и любой другой
произвольной переменной можно построить еще один цифровой идентификатор,
который уже можно передавать открыто методом GET через загрузчик фреймов.
Расшифровать такой идентификатор невозможно, так как не известны методы,
которыми он строился. Для усиления криптостойкости и вводится дополнительная
строка. А можно скомбинировать сочетание идентификатора пароля, ника и
дополнительной строки так, как угодно. Это дает возможность построить разные
системы шифрования. В любом случае — методика шифровки должна быть недоступной
всем желающим. Когда все данные переданы, фреймовая структура построена в
загрузчике, нужно опять это все перепроверить и восстановить то, что
необходимо. Перепроверяются настройки чата и служебная информация, а
восстанавливается только учетная запись вошедшего. Делается это тем же
методом, что и в Windows 2000. Производим перебор всех учетных записей,
хранящихся в базе данных. Напомню, нам нужно знать несколько вещей: переданный
методом GET уникальный идентификатор пользователя, построенный на основе
идентификатора пароля (сам пароль нигде не хранится, только его
идентификатор), Ника и дополнительной строки. Первое у нас уже есть, так как
оно передается из загрузчика методом GET, остальное считывается из базы данных
о пользователях. Итак, шифруем все подряд учетные записи точно тем же методом,
что шифровался идентификатор пароля, Ник и дополнительная строка. Полученный
результат сравнивается с переданным идентификатором пользователя: если они не
совпадают — сверяем следующую учетную запись в базе; если совпадают —
пользователь авторизован повторно; если перебор окончен, а учетная запись не
найдена — введен неверный пароль. Это кажется немного сложно, но зато дает
гарантию на правильную авторизацию и защиту от входов под любым выбранным
Ником. Конечно, я не настаиваю на абсолютности описанной защиты. Я глубоко
убежден, что все, что сделал один человек, второй может переделать и
исследовать. Но! Большой вопрос — стоит ли тратить свои усилия и знания на
такой пустяк? Описанная методика защиты не очень сложна, но накладывает
некоторые ограничения на сервер. Если учетных записей много, нагрузка будет
довольно большая. Можно пойти более легким путем — авторизовывать пользователя
по идентификатору не каждый раз, а только один, в самом начале. Дальше можно
передавать более простой идентификатор методом POST (например, номер учетной
записи в базе данных). Только это дает взломщику еще одну дырку в Вашем чате,
а это не желательно. С авторизацией покончено, пришла пора поговорить о
работе чата как о едином механизме. С теми фреймами, которые отвечают за вывод
информации, все более-менее понятно. А вот окно, где выводятся сообщения,
стоит рассмотреть подробнее. Средства HTML позволяют специальными методами
заставить окно браузера периодически обновлять свое содержимое. Это не очень
приятно на обычных страницах, но совершенно необходимо в чате. Страница с
сообщениями посетителей будет обновляться в соответствии с жестко
установленными, а чаще изменяемыми настройками. Собственно, это самая простая
часть всего чата, так как тут нужно только считать файл, куда пишутся
сообщения от посетителей, отрезать лишнюю часть сообщений (чтобы остались
только введенные последними) и вывести все на экран. Тут же можно
задействовать фильтр матов и ограничение на длину сообщения или отдельного
слова. Вот и все хитрости для этой части фреймов. Вторая по простоте часть
чата — это ввод сообщения. Тут тоже можно особо не утруждать себя,
ограничившись выбором цвета и типа шрифта, выводом иконок, контролем вводимых
сообщений и т.д. Но именно тут надо проверять авторизацию пользователя по
цифровому идентификатору. Авторизация будет проводиться всякий раз, когда
сообщение будет отправляться в чат после нажатия кнопки ОТПРАВИТЬ В ЧАТ. Это
снимает часть проблем по загрузке сервера, так как происходит отправка
сообщения в чат не так уж часто. И если пользователь не авторизован, ввод
сообщения становится недоступен — он блокируется с выводом на экран
предупреждающего сообщения. Самое сложное — применить технологию, с помощью
которой можно всегда знать, кто находится в данный момент в чате. Если
отказаться от этого сервиса, все значительно упрощается, и чат очень слабо
будет загружать сервер. Но ведь это не интересно, так что этот вариант мы
пропустим и перейдем к следующему, самому сложному по части программирования
фрейму. В нем можно увидеть, кто и сколько времени присутствует в чате. Для
реализации данной возможности нам придется и тут авторизовать посетителя по
уникальному идентификатору, и мало того, делать это с определенной
периодичностью. Ведь нужно проверять, а не появился ли в чате кто-то новенький
и не покинул ли чат кто-то из присутствующих. Чем чаще такие проверки, тем
больше нагрузка на сервер. Но вот тут-то можно ограничиться единоразовой
авторизацией, а дальше передавать простой идентификатор по методу GET. Его
хоть и можно подделать, зато программа из предыдущего фрейма ничего не
позволит сказать в чате. Ведь там будет реализована полноценная проверка
данных. Как правило, обновления можно делать раз в 15-20 секунд, а можно
добавить специальную кнопочку или ссылку, нажав на которую пользователь
обновит окно с никами присутствующих в чате. Их, конечно, надо как-то
учитывать. Делается это еще на этапе загрузчика фреймов. В специальный файл
вносятся ник входящего, время входа и контрольное время. После входа
описываемый сейчас фрейм, обновляясь с определенной периодичностью, вызывает
запись с новой информацией в файл с данными о присутствующих в чате, то есть
информация других пользователей остается неизменной, обновляется только
персональное контрольное время. Заодно проверяется контрольное время других
посетителей. Если разность контрольного времени и текущего времени больше
установленного (как правило, в 2–3 раза больше, чем время обновления фрейма),
значит или с браузером этого посетителя нет связи, или он просто закрыл окно
чата и ушел. В любом случае можно считать посетителя ушедшим, и его данные
стираются из файла данных о присутствующих в чате. Таким образом, эти
фреймы всех пользователей обновляют свое собственное контрольное время, чтобы
не быть удаленным кем-то другим, и удаляют всех, чье контрольное время
превысило установленный максимум. Дальше просто — надо только вывести на экран
список из ников, которые остались в файле. Это и есть список пользователей,
присутствующих в чате в режиме on-line. Вот и все технологии. Точнее,
конечно, не все. За бортом остались такие вещи, как персональные комнаты,
отправка сообщений на ICQ и многое другое, но это признаки профессиональных
чатов. А если Вы хотите себе именно такой, Вам придется воспользоваться
платными программами. Или даже целыми наборами программ. Но если Вы хотите
получить удовольствие от собственной разработки, если Вам достаточно простого
и не навороченного чата на собственном сайте, Вы можете воспользоваться теми
наработками, что описаны в данной статье. Еще раз повторюсь — я не претендую
на полноту и законченность своих суждений. Моя цель — побудить Вас провести
собственное исследование в области построения чатов. Я намеренно не приводил
никаких кодов, чтобы не вызвать копирования. Думайте, придумывайте, изменяйте,
творите. Приглашаю Вас посетить описанный в этой статье чат в сети Интернет по
адресу http://virtual.bresttelecom.by/index. phtml?chat/index.phtml. Там Вы
сможете увидеть работу чата, узнаете на собственном опыте все его достоинства
и недостатки.
Андрей Кухарчик virtualbrest@tut.by
|