Отправляет email-рассылки с помощью сервиса Sendsay

Все о PHP и даже больше

  Все выпуски  

Все о PHP и даже больше #11


Информационный Канал Subscribe.Ru

Все о PHP и даже больше...

.:: Путь от начинающего до эксперта ::.

# 11
7/2003

18 апреля 2003г.

Проект сайта GreatWeb.RU

Ведущий рассылки: Бабушкин Евгений

    В этом выпуске:

  • Наши проекты
  • СЕССИИ - обучение и /правильное/ использование. Часть 1
  •   Ссылки Вебмастеру:

  • Лучший хостинг
  • Раскрутка
  • Советы Web-мастеру
  • Книги по программировании
  • WEB-браузеры
  • Фоны
  • Скрипты
  • Лучшие Рассылки
  • Партнерская программа
  • DwebHost.RU

  • Привет программер!

    :.:: Наши проекты:

     

    GreatWeb.RU - Портал продвинутых юзеров. Только здесь, все о веб-дизайне, раскрутке, выбору хостинга и не только...
    Читайте здесь последние новости Инетрнет!

    Форум продвинутых юзеров. Отличный форум! Задавайте абсолютно любые вопросы, вам обязательно ответят и помогут решить Ваши проблемы.

    Совсем недавно мы открыли новую, уникальную рассылку: "Интернет новости. Будь в курсе!". Читайте описание:
    Вы хотите быть в курсе ярких событий Интернет? Тогда эта рассылка для Вас! Принципиальное отличие нашей рассылки от других:

    Первое, и самое главное, Мы публикуем самую оперативную и наиболее полную международную и российскую информацию об интернет и обо всем, что с ним связано.

    И второе, не менее важный аспект: Наши новости представляют собой легко читаемый текст, понятный не только специалистам, но и всем, кто интересуется компьютерами и интернет.

    Подписывайтесь на рассылку и Вы всегда будете "В курсе"!

    Подписаться на рассылку можно здесь.


    .:: СЕССИИ - обучение и /правильное/ использование. Часть 1


    Одна из самых важных веб-технологий - это сессии. Если вы до их не используете, то многое теряете. Давайте разберемся, что это такое.

    Будем считать, что ваш сервер настроен по умолчанию (файл php.ini) и в файлах httpd.conf или .htaccess не внесали никаких для утановки локальных php-настроек (локальных - для каталога и его подкаталогов).

    Когда нам нужны сессии?


    Ответить на этот вопрос проще ответом на другой вопрос - что мы хотим для удобной работы в PHP? Сейчас мы много чего придумаем (для облегчения программирования), потом захотим, чтобы оно само работало, а еще дальше окажется, что так и работает PHP ;-) Как только вы поймете, чего вам так не хватало, вы поймете идею сессий и технические подробности.


    Чего мы хотим для удобной работы в PHP?


    Представьте программу тестирования людей. Есть куча вопросов и куча людей. Надо постараться, чтобы люди:

    • Получали вопросы в случайном порядке (чтобы у соседа по классу вопросы появлялись в другом порядке).
    • Не могли отвечать на вопросы в произвольном порядке (меняя какие-то параметры в URL) или еще хуже - подделать кол-во набранных балов или узнать правильный ответ.
    • Не могли бросить тест и начать его заного (можно лишь дорешать до конца).
    • Могли вернуться и продолжить тестирование, при разрыве связи с сервером (модем повесил трубку).
    • Не обязаны были бы регистрироваться.
    • Могли бы работать все через один прокси сервер и с отключенными куками.
    • и т.д... еще можно много полезного придумать.


    В такой задаче надо перед началом проходжения теста взять все номера вопросов, перемешать между собой и сохранить в область данных посетителя массив номеров. Затем поместить в туже область флаг (flag=тестирование), чтобы человек не мог перейти на начало теста (начать его заного), не прорешав тест до конца. Это сделать очень просто. Предположим, что index.php - это главная страница для старта, vopros.php - страница, где выдадут очередной вопрос. Если человек с флагом "тестирование" попытается перейти на index.php, то ему надо написать - "Вы не закончили тестирование". Если человек обиделся, вырубил комп и ушел спать, через некоторый тайм аут (к примеру, через 3 дня), надо записать в историю прохождения тестов: "брошенный тест". Это похоже на игру через Интернет - если человек проигрывает, но не хочет признать это, он может как бы потерять связь с игровым сервером (якобы модем повесил трубку).

    Как это все реализовать? Очень просто. Предположим, что у каждого посетителя есть некая область памяти (у каждого - своя), в которую наша программа может что-то записывать и читать. Эта область памяти должна соответствовать всем требованиям, которые мы выдвинули выше. Наша программа не должна заботиться о ней. И все это можно сделать. Эта абстрактная область памяти имеет идеальный интерфейс. Вернее, не имеет его. К примеру, если бы данная область хранилась в файлах, нам надо было бы файлы читать и анализировать. Для записи - надо было бы записывать туда данные в каком-то формате. При хранении в базе данных - нам пришлось в начале программы выполнять SQL-запрос, чтобы извлечь все данные и в самом конце выполнения программы записать их обратно. Все это (затраты на чтение файла или базы данных) - называется интерфейс. Как я сказал, наше общение с базой данных вообще не имеет интерфейса. Это значит, что любые переменные, которые мы пожелаем, будут с некоторого момента считаться областью памяти посетителя. При каждом запуске программы, от разных посетителей, она будет иметь доступ через какие-то переменные только к персональным настройкам. Чтобы сохранить (закрепить) у пользователя какую-либо информацию в переменной, надо просто записать в эту переменную что-нибудь. К примеру, в программе авторизации пользователей, говорим "хочу, чтобы $auth стала частью областью памяти". Если человек вводит свой логин и пароль (их мы проверяем как-то, например по базе данных), то мы записываем в переменную $auth единичку, затем в аналогичную переменную $login его логин. Пароль записывать не надо, т.к. наличие единицы в переменной $auth уже будет означать, что человек прошел авторизацию. На всякий случай будем хранить еще и логин. Пароль хранить совершенно не нужно, т.к. нет случая его применить... кроме как вывести на экран (но это уже будет глупая затея, а не реальная программа). Таким образом, мы один раз устанавливаем $auth, а дальше в любом месте может проверить авторизированность пользователя if ($auth) или if ($auth==1). Так как переменная $auth будет частью области памяти, то можно не бояться, что какой-нибудь злой хакер запустит нашу программу как programm.php?auth=1 и окажется авторизированным.


    Подведем итог нашей мечте о комфортной работе

    Все, о чем тут было сказано, как не трудно догадаться по названию, называется сессия. Принцим действия следующий (забудьте пока о том, как это все работает):

    • Чтобы сохранить о пользователе что-то, выберем для этого переменную и сообщим php-процессору о нашем желании с помощью session_register("auth") и session_register("login"). Это называется регистрация переменной. Эти строчки пишут в начале программы, чтобы PHP-код, идущий ниже в программе, мог обращаться к $auth и $login.

    • Если мы что либо запишем в $auth и/или $login, то эта переменная будет сохранена в персональную область данных посетителя. Это значит, что при следующем вызове той же программы (или из того же каталога или подкаталогов), перед началом работы php-скрипта, php-процессор узнает пользователя и загрузит сохраненные для него переменные (если когда-либо в них что-то записывалось).

    • И самое главное - вся информация в сессиях не может быть подделана пользователем. Т.е. наличие единицы в какой-то переменной сессии означает, что туда ее могла записать программа, а не кто-либо.

    Еще раз скажем "итак" и подведем итог. Мы хотим, чтобы PHP-процессор умел распознавать пользователей и предоставлял в свободное распоряжение программе область памяти (в виде переменной $auth, $login или $любое_название), которую невозможно никак подделать. Всех новых пользователей PHP-процессор тоже должен распознавать и присваивать им новую область памяти. Единственное, что сможет злой пользователь - прикинуться новым пользователем или вообще бросить наш сайт.


    Как устроены сессии: идентификатор посетителя

    Выше был описан принцим сессий. Их придумали для того, что PHP лишен такой нормального свойства программы - хранить что-либо о пользователе. И виноват тут не PHP. Если взять что-то другое - средневековый язык Perl или язык ASP (для тех, кто решил тормознуть P4 1700Mhz dual), они будут работать по тем же самым принципам. И будут лишены того же - способностью что-то созранить о пользователе. Это происходит из-за убогости Web'a. Но задача программиста не придумывать что-то, а писать программы, работающие в любой среде.

    Вернемся к устройству сессий. С помощью чего PHP-процессор различает пользователей? С помощью идентификатора. Он является 128 битным числом. Если человек пришел на сайт впервые и PHP-процессор это видет, то данному посетителю присваивается какое-то случайное число, не присвоенное еще никому. В дальнейшем, при повторном заходе, посетитель будет ассоциирован с его личным числом (идентификатором), из-за чего программе будет предоставлена персональная область памяти.

    Запомните главное - если суметь передать идентификатор от одной страницы (PHP-скрипта) до другой (до следующего вызова с нашего сайта), то мы сможем различать всех посетителей. Больше, от не удобного для программиста Web'а, ничего не требуется. Так как мы выбрали очень больше число, то не существует ни малейшего опасения, что злой хакер подделает число, тем самым воспользуется чужой областью данных. Запомните еще одну главную мысль - подделать сессию или идентификатор нельзя. Число из 128 бит (это 2 в 128 степени) в десятичном представлениим имеет 38 нулей. Пердположим, на вашем сайте будет 10 000 посетителей. Тогда у хакера шансы несколько возрастают до 2 в степени 114. Но это по прежнему нереальная вероятность, что либо подделать. Одна из очевидных причин следующая. Чтобы подобрать номер сессии, нужно сделать запрос к вашему веб-серверу. Пусть каждый запрос занимает 1024 байта. Через миллиард обращений к вашему сайту, что составит 1000 ГБ трафика, явно что-то случиться:

    • Ваш сайт отключат из-за дикого трафика или у вас не хватит денег на оплату такого большого трафика (по 36 баксов за ГБ - $36000). Дешевле нанять группу товарищей для взлома сервера или группу товарищей в черной одежде для простого выноса сервера :-)
    • Ваш канал или пропусканая способность провайдера слишком слабая, чтобы в разумные сроки перебрать все номера.
    • Ваш сервер не сможет хоть как-то быстро работать, имея гигантское количество пустых файлов, из-за создания фиктивных сессий.
    • Ваш сервер переполниться лог файлами и файлами фиктивных сессий, перестанет работать.
    • Всех хакеров посадят за целенаправленную и длительную атаку.

    Хоть сессию подделать нельзя, но существуют следующие непредвиденные случаи:

    • На компьютере посетителя побывал злой хакер, который поставил злую программу, ворующую пароли от интернета (статья N##) и номера сессий.
    • Между компьютером посетителя и сервером сидит злой хакер и видит все, что передается. Конечно, есть защищенный (зашифрованный) протокол SSL, но это увы везде не внедрить.
    • Ккомпьютеру нашего посетителя подошел злой сосед и стащил этот номер сессии.


    Как видите, все основано на том, что кто-то что-то у кого-то стащит. Но это уже не проблема программиста. Представьте, вы написали идеальную программу, в которой нет ошибок и дыр для взлома, а через день злой хакер взломал сервер и скопировал / изменил / удалил все, что посчитал нужным, даже не запуская программу. Еще раз заметим, хоть вариант стащить сессию есть, только это уже проблемы другого рода.

    Выглядит этот несчастный идентификатор обычно так: "7f4cbf53fbcd4717792447f32da7dba8", или так: "ac4f4a45bdc893434c95dcaffb1c1811". Это текстовая запись 128-битного числа (занимает 32 байта).


    По умолчанию, PHP сам заботиться о том, чтобы обнаружить идентификатор или выдать новый новому посетителю.


    Как устроены сессии: где хранится информация

    Выше мы установили, что для нашей мечты нужно постараться передавать идентификатор от вызова к вызову (как именно передают - через главу). Имея идентификтор (число) легко загрузить каждому пользователю его персональные данные. Есть два популярных способа хранинения - база данных и файлы. Еще можно хранить сессии в памяти сервера (ОЗУ), но при выключеннии сервера будут потеряны сессии. Обычно сессии хранят в файлах, чтобы снизить нагрузку на базу данных. В огромном числе задач сессии позволяют полностью отказаться от базы данных. Или использовать ее миниматьльно: в базе данных только список логин/паролей, в сессиях (на файлах) вся рабочая информация.

    По умолчанию, PHP хранит все в файлах (в своем формате) и сам достает из них сохраненные данные. После работы каждого скипта PHP сам все записывает обратно в личный файл из переемнных, помеченных для хранения в сессии.



    Как устроены сессии: сериализация

    Если вы посмотрите на файл сессии, то увиде нечто такое:

    myarray|a:4524:{s:7324:"startup";i:98;s:4:"type";i:1;s:2:"ip";s:13:"1572342";s
    :2:"tt";i:2;s:3:"b";i:12312;s:621:"max";i:2380;s:6:"min";i:-8334;s:10:"realmax
    ";i:1213126;s:10:"realmin";i:0;s:1:"kol";i:1;s:1:"n";i:15;s:9:"timestart";i:98
    8387008;s:7:"timeend";i:9883218;s:4:"list";a:16:{i:0;s:7:"1002001";i:1;s:7:"10
    02007";i:2;s:7:"1002010"; ............ и т.д.

    Представьте, у нас есть огромный массив сложной структуры, к примеру, $myarray. Вам будет интересно узнать, что любую перменную (сложный массив) с любыми символами (произвольные бинарные данные) очень легко запаковать в строку из букв и цифр. Для чего переводить массив в строку? Строку (просто переменная), да еще и текстовую, легко куда-нибудь записать. Например, на листочек бумаги. Или в базу данных... Или в файл сессии. Позже, можно распаковать такую строку в оригинальную переменную и получить то, что было до упаковки. Данный метод (называется - сериализация) упаковки/распокавки переменных или объектов применяется не только в сессиях. Просто PHP, чтобы сохранить все данные пользователя, запаковывает их и кладет как строку в файл сессии.

    $myStr=serialize($myVar) - запаковать огромный массив или любую произвольную переменную $myVar в текстовую переменную $myStr.

    $myVar=serialize($myStr) - распаковать (восстановить) данные из ранее запакованной переменной, хранящейся в $myStr, и записать результат распаковки (оригинальную переменную) в $myVar

    По умолчанию, программиста не должно волновать, как именно PHP хранит ваши переменные :-) Вы всегда можете перейти от метода хранения сессий в файлах, к хранению в базе данных или любых других местах, просто дописав нужный модуль по сохранению/извлечению сессий. Менять что-либо в программе не придеться!

    Продолжение статьи читайте в следующем номере этой рассылки!

    Источник: php.spb.ru (Дмитрий Бородин)

    © 2002-2003 Copyright by GreatWeb Design
    Копирование материалов рассылки возможно только в случае явного указания на сайт "GreatWeb.RU" как на источник информации.



    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Отписаться
    Убрать рекламу

    В избранное