Содержание

Работа IP.Board с внешним реестром пользователей

Нередко проскакивает у людей желание скрестить два продукта. Однако, не многие знают, что в IP.Board уже заложена возможность (с версии 2.1.x) работы с внешними хранилищами пользователей (например, таблица пользователей в базе данных другого продукта).

Механизм работы с внешним реестром построен на простом предположении, что все продукты так или иначе содержат таблицу пользователей, в которой 100% присутствуют поля с логином, паролем и основным email'ом пользователя. Этот же набор данных использует и IPB при идентификации пользователя.

Как это работает.

Теория

Существует два варианта работы с внешним реестром.
1. «Passthrough» («удаленный») - форум при получении идентификационных данных (пары login и password, или email + password) обращается к внешней таблице с пользователями и в ней ищет пользователя, удовлетворяющего этим данным.

Стоит заметить, что обращение происходит не всегда. В случае когда осуществляется идентификация администратора, то делается запрос только к внутренней таблице пользователей (ibf_members)

2. «OnFail» («совместный») - форум пытается найти пользователя в своей внутренней таблице и в случае неудачи обращается к внешней таблице, как к последней инстанции.

Второй вариант предусмотрен не просто так, он действительно бывает полезен, когда внешний реестр подключается к уже давно работающему форуму. Но главное данный метод может использоваться для объединения двух и более форумов IP.Board!

Практика

В теории как можно заметить все просто. Но в ней не отражен важный момент - завязка всех остальных данных (тем, сообщений, приватных сообщений) осуществляется на уникальные идентификаторы из внутренней таблицы пользователей.

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

Как сделать?

Начнем с настроек. В АЦ перейдем на вкладку «НАСТРОЙКИ». Запустим «Создать новый метод» из группы «Методы авторизации».

Название, описание - не представляют никакого интереса для нас, пропускаем.

Имя директории - имя поддиректории в которой будут находится два стандартных для авторизационного метода скрипта (auth.php и conf.php). Сама поддиректории располагается по пути ./sources/loginauth.

Тип авторизации? - два варианта. Названия и принцип работы совпадают с теми что были приведены выше.

Служебный URL для пользователей - данный пункт имеет смысл только при «удаленном» типе работы метода. В данном поле пишется полный адрес формы с использованием которой пользователь может изменить свой пароль и email.

Форма должна изменять данные во внешнем реестре! При этом реализация данной формы может быть как ваша, так и стороннего программиста, который разрабатывал продукт, с базой которого вы работаете (имеется ввиду в самом продукте есть некоторая панель управления профилем зарегистрированного в системе пользователя)

URL регистрации - как и предыдущий пункт данный работает только при «удаленном» типе работы метода. В поле может быть указан адрес на форму регистрации в стороннем продукте.

HTML форма авторизации - поле остается загадкой для меня. По идее, оно должно заменять стандартную форму входа на форуме, но почему-то только рисуется сверху нее.

Но еще интересно и то, что ниже следующая опция позволяет назначить форму входа по другому адресу. Так что смысла в описании HTML формы не вижу вообще.

Ссылка авторизации для пользователей - полный адрес формы с которой можно будет авторизоваться на форуме или в интегрированной среде форум + сторонний продукт. Автоматический вешается на кнопку «Вход» в форуме.

Ссылка завершения сеанса для пользователей - полный адрес скрипта который позволит завершить сессию пользователя на форуме или в интегрированной среде форум + сторонний продукт. Автоматически вешается на кнопку «Выход» в форуме.

Включить метод? - сделать метод авторизации активным.

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

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

Также не очень понятна данная опция.
Обращаю внимание, что обязательными к заполнению являются только опции: название метода и имя директории. Остальные опции могут быть реализованы иначе! Но об этом ниже.

Программная реализация авторизации.

Будем рассматривать на примере скриптов из ./sources/loginauth/external/ (там приводится пример объединения IP.Board с таблицей пользователей абстрактного форума phpBB, вы такой не знаете случайно? ;) )

Реализация разбита на две части.

  1. Конфигурационная часть. [ ./sources/loginauth/external/conf.php ]
    По замыслу разработчиков должен содержать некоторый конфигурационный массив (например, $LOGIN_CONF).
  2. Авторизационная модель. [ ./sources/loginauth/external/auth.php ]
    Здесь должна реализовываться логика авторизации с использованием внешнего реестра. Либо более простыми словами - подключение к внешней базе, запрос пользователя по логину из таблицы пользователей и, наконец, сравнение паролей полученного из таблицы и введенного пользователем.

Теперь когда краткий экскурс в программную реализацию дан, с удовольствием растечемся мыслей по древу. Более подробно по каждой части.

Конфигурационная часть.

В нашем примере скрипт содержит массив. В массиве представлена информация об адресе удаленного сервера, имени базы данных, логине и пароле пользователя для этой базы. Эти данные используются в авторизационной моделе при соединении с другой базой. Самое интересное в конфигурации идет ниже.

REMOTE_TABLE_NAME - имя таблицы в которой хранятся пользователи.
REMOTE_TABLE_PREFIX - ну как же без префикса.

Префикс обязательно надо указывать, если он есть, не пытайтесь извернуться и вписать имя таблицы с префиксом. Все потому что запросы к внешней базе идут все через тот же драйвер баз данных, что и в IP.Board.

REMOTE_FIELD_NAME - имя поля таблицы в котором хранится логин пользователя.
REMOTE_FIELD_PASS - имя поля таблицы в котором хранится пароль пользователя.
REMOTE_EXTRA_QUERY - дополнительное условие к запросу для получения пользователя из таблицы.

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

Хочется заметить, что конфигурационная часть может быть реализована и совершенно иначе нежели в существующем примере. Если вам стало интересно, то еще один пример реализации конфигурационной части можно найти в модуле авторизации для LDAP

Авторизационная модель.

Данная часть в отличие от конфигурационной должна быть реализована по определенному шаблону (на языке ООП имя ему интерфейс).

Это должен быть класс login_method наследуемый от login_core. В классе обязательно должен быть атрибут $ipsclass в который будет передаваться объект супер-класса при работе метода. Должен быть реализован, как минимум, метод authenticate, который принимает два значения: логин 1) пользователя ($username) и введенный им пароль ($password), и возвращает состояние системы авторизации после проверки данной пары по внешнему реестру.

IP.Board в стандартном исполнении (не модифицированный) распознает пять состояний:

Последнее состояние выставляется самим IP.Board и является служебным. Поэтому нет смысла использовать его в своем модуле. В каких случаях система авторизации переходит в состояние METHOD_NOT_DEFINED будет описано позже

Итак, основная работа модуля авторизации заключается в методе authenticate. Алгоритм метода достаточно прост:

  1. Убедиться, что если метод работает в «удаленном» режиме и происходит вход в администраторскую часть, то проверить пользователя по внутреннему реестру, дабы не отрезать локально созданных администраторов.
  2. Присоединится к внешнему реестру (в нашем примере это удаленная база данных).
  3. Попробовать получить пользователя из внешнего реестра по введенному логину (запрос к таблице с указанными именами полей, в которых хранятся логин и пароль).
    1. Если запрос к реестру ничего не вернул, то перевести систему авторизации в состояние NO_USER и передать управление IP.Board.
  4. Сверить полученный в запросе 3 пароль с введенным пользователем.
    Обычно для этой цели выделяется отдельный метод _compare_passwords. Который принимает два пароля и в соответствии с некоторой логикой сравнивает их. Что такое логика? Сравнивать обыкновенно приходится некоторый хэш (hash) пароля из реестра и чистый (plain-text) пароль. Естественно для приема решения о совпадении паролей их необходимо привести к одному виду, а так как хэширование это однонаправленная функция (нет обратного преобразования hash→plain-text), то хэшируют чистый пароль. Хэширование может быть многоэтапным с добавлением соли (salt) и с применением различных криптографических алгоритмов - это и есть логика.
    1. В случае различия паролей - перевести систему авторизации в состояние WRONG_AUTH и передать управление IP.Board.
  5. Попробовать загрузить информацию о пользователе из локального реестра. Данное действие есть попытка проверить наличие данного пользователя в локальной базе. Для чего нам необходима локальная запись о пользователе уже объяснялось.
    1. Если пользователь в локальном реестре не найден, попробовать его создать.
      1. Если создать не получилось, то перевести систему авторизации в состояние NO_USER и передать управление IP.Board.
      2. В противном случае - перевести систему в состояние SUCCESS

Собственно в теории это так, а за кодом обращаемся в ./sources/loginauth/external/auth.php

Прочие методы модуля авторизации

Да да, вы не ослышались, модуль авторизации может иметь еще несколько методов, которые могут быть полезны. Как раз эти методы позволяют не заполнять большую часть полей при создании метода авторизации в админцентре.

create_account( $password )

Входной параметр - массив с данными регистрируемого пользователя. Сам метод предназначен для создания новой учетной записи во внешнем реестре при регистрации пользователя через IP.Board. Если метод не определен в auth.php, то система авторизации перейдет в состояние METHOD_NOT_DEFINED, тем самым система прекратит реагировать на часть ошибок связанных с невозможностью регистрации пользователя.

Для create_account крайне важно определение другой функции:

email_exists_check($email)

Входной параметр - email адрес. Метод позволяет проверить наличие такого же email адреса во внешнем реестре при регистрации пользователя через IP.Board. Если метод не определен в auth.php, то система авторизации перейдет в состояние METHOD_NOT_DEFINED, тем самым прекратит реагировать на часть ошибок связанных с невозможностью регистрации пользователя.

Если реализуете в своем модуле create_account, то обязательно реализуйте и email_exists_check, иначе система будет не стабильно работать (если вообще будет)!
change_pass($email, $new_password)

Входные параметры - email пользователя и новый пароль в plain-text формате. Метод предназначен для изменения во внешнем реестре пароля у существующей учетной записи пользователя. Вызывает при попытке изменить пользователем свой пароль через панель пользователя в IP.Board. Если метод не определен в auth.php, то система авторизации перейдет в состояние METHOD_NOT_DEFINED, тем самым система прекратит реагировать на часть ошибок связанных с невозможностью смены пароля.

change_email($old_email, $new_email)

Входные параметры - старый email пользователя во внешнем реестре и новый. Метод предназначен для изменения email адреса у существующей учетной записи пользователя во внешнем реестре. Вызывает при попытке изменить пользователем свой email адрес через панель пользователя в IP.Board. Если метод не определен в auth.php, то система авторизации перейдет в состояние METHOD_NOT_DEFINED, тем самым IP.Board прекратит реагировать на часть ошибок связанных с невозможностью смены адреса.

За примером реализации методов можно сходить в ./sources/loginauth/ipconverge/auth.php

http://www.zulus.ws/2007/07/09/ipboard-and-external-user-database/

1) В дальнейшем под «логином» я понимаю как имя пользователя так и его email адрес. Другими словами в зависимости от задачи логином может быть имя пользователя, а может быть и email.