Защищенный ajax-чат на php
Готовясь к переезду на новый сервер (старого стало не хватать), стал разгребать всякий хлам. Натолнкулся на много интересных вещей, о которых давно не вспоминал. Некоторые, на мой взгляд, достойны того, чтобы упомянуть их на страницах блога, так как при их разработке приходлилось тратить много времени на поиски различных решений и приемов. Сегодня расскажу (и покажу) про защищенный ajax-чат.
Для начала, ссылка на демо. Кстати, это новый раздел на сайте, который я добавил специально, чтоб выложить пример ajax/php чата, ну и в перспективе, думаю полезная будет вещь. Исходники чата можно скачать в конце статьи.
Как то столкнулся я с задачей написать простенький ajax-чат, который предпологалось использовать из офиса. Тут я подумал, что мне бы было не комфортно общаться в таком чате, зная, что потенциально кто угодно может просмотреть переписку — cовременные программы для прослушивания сетевого эфира (sniffers) позволяют это делать без особого напряга. Немножко пораскинув мозгами я прикрутил к ajax-чату симметричное шифрование. Сразу можно возразить, мол, как можно называть такой чат защищенным, ведь ключ можно перехватить. Все не совсем так, поскольку ключ не передается. И так, идея простая. Два человека (или больше) заранее придумывают ключ, а затем вводят его в специальном поле. После применения такого ключа весь отсылаемый трафик будет шифроваться этим ключом, а принимаемый расшифровываться. Пока человек не введет ключ, ему будет приходить бессмысленный набор символов, а его сообщения вообще не будут шифроваться. Таким образом, этот чат можно использовать и вообще без шифрования.
Лог разговора ведется на сервере, но владелец сервера не сможет прочитать переписку, если не знает ключа шифрования.
Чтобы попасть в чат, нужно пройти авторизацию. Процедуру авторизации я не стал городить сложную. Когда пользователь заходит на страницу чата, скрипт проверяет через параметры http-сессии. Если пользователь не авторизован, ему генерируется форма логина, которая содержит параметр SALT — это так называемая техника соления. Соль (случайный набор символов) генерируется на сервере и сохраняется в сессии.
function getSalt() { $al = '0123456789abcdef'; $res = ''; for ($i = 0; $i<16; $i++) $res .= $al[rand(0,15)]; $_SESSION['salt'] = $res; return $res; }
Клиент при хэшировании текста применяет эту соль. Когда посоленный хэш приезжает на сервер, скрипт сравнивает это значение с эталонным с учетом соли, взятой с сессии. За счет такого подхода достигается некоторая безопасность при открытой авторизации (по обычному http).
function checkLogin($hash) { $password = 'mypass'; // один пароль на всех $users = array('user1','user2','user3'); //список допустимых пользователей error_log('checkLogin:' . $hash . ' salt:' . $_SESSION['salt']) ; foreach ($users as $user) { $m = md5($user . '|' . $password . '|' . $_SESSION['salt']); if ($m == $hash) return $user; } return false; }
При желании можно заменить на какой-нибудь свой механизм авторизации, или совсем от него избавиться, если в нем нет необходимости.
Вся магия шифрования разговоров реализуется следующей javascript-функцией
function encrypt_str(str) { if (cKey == '') return encode(str); var xor_key= cKey; var to_enc =str; var the_res=""; for(i=0;i<to_enc.length;++i) the_res+=String.fromCharCode(xor_key ^ to_enc.charCodeAt(i)); return encode(the_res); }
, где cKey, собственно, ключ шифрования, введенный в поле Cipher.
Алгоритм, конечно, не претендует на Оскара, но от школоты, скачавшей снифер, поможет. Опять же, никто не мешает дофантазировать.
P.S. Неохота писать отдельный пост, поэтому опубликую здесь несколько новостей, касающихся сайта, тем более, что пост находится в категории Блог.
1. Добавил, наконец-то, в ТВ-программу описания передач. Изначально я этого не сделал из соображения экономии места, когда сайт еще работал на виртуальном хостинге. Сейчас же с этим проблем нет.
2. Доработал скрипт загрузки новостей таким образом, что картинки к новостям теперь имеют одинаковый размер (ширину и высоту) и плюс прикольное обрамление в виде рамки со скругленными углами (подсмотрено у Apple). Вдобавок, доработал механизм обнаружения дублирующих новостей. До этого заголовок проверялся только на полное совпадение. Сейчас заголовок проверяется по списку из уже существующих записей за 24 часа. Если обнаруживается запись, в которой совпадают хотя бы два слова, новость расценивается как дубликат. Слова из двух и одной буквы не учитываются при поиске, поэтому изредка дубликаты все-таки прорываются.
3. Местами отрихтовал html/css верстку.
4. С ужасом обнаружил, что сайт работает с базой данных из-под учетной записи c неограниченными полномочиями. Перевел на ограниченного пользователя со строгим списком грантов.
Спасибо тебе, добрый человек))