ПРОЕКТЫ 


  АРХИВ 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 


Модули Apache 

Прочие программы 


ПИШИТЕ
ПИСЬМА














     ПРОГРАММЫ :: Модули Apache

[English version]

mod_uid.c version 1.1

модуль, выдающий "правильные" cookies для подсчета посетителей сайта

Download: ftp://ftp.lexa.ru/pub/apache-rus/contrib/

Оглавление

  1. Copyright
  2. Назначение
  3. Установка (Apache 1.x)
  4. Установка (Apache 2.0.x)
  5. Конфигурация
  6. Формат cookie
  7. Что можно записать в лог
  8. Почему не mod_usertrack
  9. TODO

Copyright

Copyright (C) 2000-2002 Alex Tutubalin, lexa@lexa.ru

Допускается распространение и использование в производных продуктах на условиях аналогичных Apache License - должен быть сохранен копирайт автора и ссылка на http://www.lexa.ru/lexa, производный продукт не должен называться mod_uid

Прототип этого модуля был сделан автором при работе в компании Rambler, данная версия cущественно переработана

Автор благодарит Дмитрия Хрусталева за ценные советы.

Описание

Стандартные средства Apache не дают разумных средств трэкинга пользователей (о проблемах mod_usertrack написано ниже), данный модуль их предоставляет.

Что он делает:

  • если пользователь отдал заголовок Cookie с правильным cookie-name, то записывает эту Cookie в notes c именем uid_got (потом, соответственно, это можно записать в лог)
  • если пользователь пришел без нужной cookie - выдает ему заголовок SetCookie и записывает выданную cookie в notes с именем uid_set (и это можно тоже записать в лог)
  • если включена встроенная поддержка P3P, то при выдаче заголовка Set-Cookie выдается и заголовок P3P

Достоинства:

  • в cookie присутствует дата ее выдачи и "номер сервиса" (т.е. число, задаваемое при настройке), что позволяет понять когда пользователь пришел на наш сайт впервые и куда именно он пришел.
  • поддержана многосерверная работа - при аккуратной настройке (либо при полном ее отсутствии :) гарантируется, что выданная пользователю cookie будет уникальна
  • выданная пользователю и полученная от него cookie не смешиваются в лог-файле
  • cookies имеют длину 128 бит, что позволяет для работы с ними в анализаторе логов (быстрый поиск и т.п.) использовать готовый код, предназначенный для работы с IPv6 (например, libpatricia)
  • Поддержана P3P (в минимальном объеме)

Установка

При конфигурации Apache к параметрам ./configure нужно добавить --add-module=/path/to/mod_uid.c:
tar xzvf apache_1.3xxx
tar xzvf mod_uid-1.0.xx.tar.gz
cd apache_1.3xx
./configure --prefix=/usr/local/apache ... --add-module=../mod_uid_1.0.xx/mod_uid.c other-params
make
make install

Установка (Apache 2.0)

Для работы с Apache 2.0 предназначен модуль mod_uid2.c
Сначала необходимо установить Apache 2.0.x, предположим, мы сделали это в директорию /usr/local/apache
Для установки модуля mod_uid2 нужно использовать программу apxs:
tar xzvf mod_uid-1.xx.tar.gz
cd mod_uid-1.xx
/usr/local/apach/bin/apxs -i -c -a mod_uid2.c
эта команда скомпилирует модуль (ключ -c), установит его в каталог Apache (ключ -i) и активирует модуль добавлением команды LoadModule в httpd.conf (ключ -a)

Конфигурационные директивы

Все конфигурационные директивы можно указывать где угодно - Server/VirtualServer/Location/... При указании в .htaccess должно быть разрешено AllowOverride FileInfo (или All)

UIDActive On/Off
включить-выключить выдачу cookie.
Если выдача выключена, то полученные от клиента cookies все-равно раскодируются и могут быть записаны в log.
Default: On

UIDCookieName string
Имя cookie (default - uid)
Имя cookie, выдаваемой клиенту. Не должно пересекаться с какими-то другими именами, используемыми на сайте.

UIDService number
"Номер сервиса" - строго положительное (ненулевое) уникальное число, идентифицирующее данный сервер в кластере, либо данный документ/набот документов.
Данный номер используется для двух целей:
  1. Если используется несколько серверов внутри одного домена (с одинаковым параметром cookie domain=), либо с одним hostname, то задание разных UIDService приводит к тому, что выдаваемые разными серверами cookies с гарантией будут уникальными.
  2. Использование разных UIDService для разных разделов сервера позволяет при анализе логов выяснить, на какой из разделов клиент пришел в первый раз.
Default: IP-адрес сервера.

UIDDomain .domain.name
Имя домена для которого выдается кука
В многосерверных конфигурациях позволяет иметь общее пространство cookies для всех серверов (например, для mail.rambler.ru, www.rambler.ru, info.rambler.ru используется домен .rambler.ru)
Если нужно выключить domain= для какого-то набора документов, оставив его включенным для сервера в целом, в соответствующем разделе конфигурации (Location/Directory/...) нужно использовать UIDDomain none
Defaulut: нет домена т.е. пользовательский браузер будет возвращать cookie только на исходный сервер.

UIDPath string
Путь для которого выдается cookie (параметр path= в Set-Cookie:)
Default: /

UIDExpires number
UIDExpires plus 3 year 4 month 2 day 1 hour 15 minutes
Задание Expiration date для cookie.
UIDExpires number - прибавить number секунд к текущему времени UIDExpires plus 3 year 4 month 2 day 1 hour 15 minutes - то же самое, но выраженное по человечески.
Default: прибавляется 10 лет к текущей дате

UIDP3P On/Off/Always
Управление выдачей заголовка P3P одновременно с выдачей cookie.
Варианты:
  • Off - не выдавать заголовок P3P
  • On - выдавать только если у Cookie выдается параметр domain
  • Always - выдавать всегда (т.е. даже без domain)
Default: Off
Эта директива нужна для удовлетворения ME IE6+ в многосерверной конфигурации и, например, включения кода "счетчика" с другого сервера на страницу. В случае, когда cookie выдается без domain= или domain "покрывает" текущее имя сервера для основного документа MS IE6+ с настройками по-умолчанию удовлетворится и так, однако для составных документов, собранных с разных серверов, cookie могут подавляться.
mod_uid выдает только заголовок P3P (по-умолчанию - только с compact policy), поддержка /w3c/p3p.xml и подобного остается задачей владельца сервера.
Заголовок P3P выдается только если mod_uid выдает заголовок Set-Cookie, т.е. если у вас выдаются и другие cookie и для них тоже нужен P3P, то задачу выдачи P3P нужно решать отдельно и самостоятельно.

UIDP3PString string
Текст заголовка P3P, выдаваемый клиенту.
Default: CP="NOI PSA OUR BUS UNI"

Формат Cookie

Формат куки: В двоичном виде: unsigned int cookie[4], где
    cookie[0] - "номер сервиса" (задается через UIDService)
    cookie[1] - время выдачи (unix time)
    cookie[2] - pid процесса выдавшего куку
    cookie[3] - старшие 24 бита - уникальный секвенсер в пределах процесса (стартовое значение - 0x030303),
    младшие 8 бит - номер версии куки (сейчас - 2)
Эти 128 бит переводятся в network byte order, кодируются в base64 и отдаются клиенту (в версии 1 все отдавалось в host order, что затрудняло поддержку кластеров серверов с разной архитектурой).
Уникальность
Очевидно, что полную гарантию может дать только страховой полис и если в пределах одного домена будет выдано более чем 2^128 cookies, то какие-то из них будут повторяться. Однако при разработке формата cookie были приложены усиля к тому, чтобы при разумном количестве cookies они были бы уникальными.
  1. В случае, если "номера сервиса" уникален (свой у каждого сервера) в пределах данного домена, разные серверы будут с гарантией выдавать разные cookies.
  2. Включение в cookie времени выдачи и pid подразумевает, что pid-ы разных процессов не повторяются в течение одной секунды. На всех известных мне Unix-системах это так - pid-ы монотонно возрастают до некоего максимума - 2^16 или более - т.е. для повторения cookie[1]/cookie[2] в рамках одного сервера нужно делать больше чем 2^16 fork() в секунду, что на сегодняшний день малореально.
  3. Секвенсер (старшие 24 бита в cookie[3]) позволяет удостовериться в уникальности cookie в пределах одного процесса в течение одной секунды. Разрядность секвенсера позволяет выдавать до 1.0E+07 cookies одним процессом в секунду.

Что можно записать в лог

mod_uid пишет в notes ("заметки") одно из двух значений:
  1. Если от клиента была получена cookie, она помещается в note "uid_got"
  2. Если клиенту была выдана cookie, она помещается в note "uid_set"
Cookies пишутся в лог как 4 32-битных 16-ричных числа в host-order (т.е. для версии 2 производится преобразование network-host, для версии 1 - все пишется как есть в предположении, что архитектура сервера с момента выдачи cookie не изменилась) В LogFormat эти notes можно использовать в виде \"%{uid_got}n\" и \"%{uid_set}n\" соответственно.
При использовании LogFormat такого вида:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\"
\"%{User-Agent}i\" \"%{uid_got}n\" \"%{uid_set}n  combined_cookie
мы получим примерно такие записи в log-е
Выданная клиенту Cookie:
62.104.212.93 - - [05/Jan/2002:00:02:06 +0300] "GET / HTTP/1.0" 200
13487 "-" "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x
4.90)" "-" "ruid=000000013C36184E00009A2100002901" 

Полученная от клиента Cookie:
216.136.145.172 - - [05/Jan/2002:00:14:59 +0300] "GET /buttons/but-support-e.gif
 HTTP/1.0" 200 252 "http://apache.lexa.ru/english/meta-http-eng.html" 
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" 
"ruid=000000013C361B5000009A0100009501" "-" 
Такой формат без проблем понимается распространенными анализаторами логов, включая Webtrends, который по такому логу с удовольствием считает Visitors.

Почему не mod_usertrack из поставки Apache

Потому что у него есть несколько недостатков:
  • нет гарантий, что двум пользователям не будет выдана одинаковая cookie, хотя конечно включение getpid(), remote_ip и времени до миллисекунд сводит эту вероятность к минимуму
  • нет поддержки многосерверной работы - а в этом случае возможность выдачи одинаковой cookie возрастает
  • в логе хочется иметь возможность видеть и выданную пользователю cookie, причем видеть ее отдельно, mod_usertrack их перемешивает.
  • Хочется иметь "номер сервиса" (см. выше) - чтобы понимать на какой из наших сервисов пользователь зашел при первом своем визите.

TODO

  1. Поддержка разных форматов (Netscape/Cookie/Cookie2 - как в mod_usertrack), но только если появится реальная необходимость - пока таковой необходимости не замечено.
  2. Есть смутное подозрение, что на multithread-apache и многопроцессорных машине инкремент sequencer-а нужно обложить mutex-ами

 




Copyright © Lexa Software, 1996-2009.