« Заметки про java и загрузку файлов с помощью commons fileupload | Hessian связывает flash и java » |
OpenID. Обзор библиотеки joid
Сегодня я устрою тест еще одному серверу и consumer-у openid. Этот кандидат прибыл с экзотического острова Явы, так что ставить его в один ряд с описанными в прошлой статье библиотеками нельзя. Требования к хостингу у него будут повыше, да и процедура настройки и установки требует знания основных идей из мира java. Библиотека называется joid (полагаю, сокращение от java openid). Технически кандидат обещает, что сможет понять и версию 1.0 и 2.0 протокола openid. В рекламных проспектах говорится о простоте использования (читай, создания собственного сервера или consumer-а использующего функции joid). Домашняя страничка библиотеки http://code.google.com/p/joid/. На ней вы можете почитать куцую документацию, на странице downloads вы можете скачать саму библиотеку в виде архива joid-1.0.2.jar. Толковых описаний в сети "step by step" по использованию библиотеки я не нашел: пара страничек тупо копировали приведенный на странице проекта пример кода и расхваливали ее простоту и малый размер. Так что придется исправлять этот недостаток.Скачанный архив библиотеки joid-1.0.2.jar я исследовал вдоль и поперек, и получил стойкое ощущение, что чего-то не хватает: в README шли ссылки на отсутствующие в архиве файлы и каталоги. Попытка решить проблему в лоб, создав веб-приложение (для теста я использовал apache-tomcat-6.0.14) поместив в папку lib библиотеки по следующей инструкции:
- Copy joid.jar, log4j-*.jar, and tsik.jar to your lib directory (so they end up in WEB-INF/lib).
- Add OpenIdFilter to your web.xml (see below for how to add it)
- бла-бла-бла
Так вот эта попытка закончилась неудачей: java.lang.ClassNotFoundException: org.verisign.joid.consumer.OpenIdFilter. Так что я выкачал весь проект из SVN. В его состав вошли следующие папки:
- examples
- lib
- resources
- src
- stores
- test
В папке lib находились нужные для работы приложения библиотеки: ant-junit.jar, commons-codec-1.3.jar, commons-httpclient-3.1-rc1.jar, commons-lang-2.3.jar, commons-logging-1.1.jar, javax.servlet.jar, junit-3.8.1.jar, log4j-1.2.13.jar, tsik.jar.
Из них только последняя библиотека является редкой (я так и не смог выяснить в составе какой другой системы или продукта она идет). Так что выкачивать целиком проект из репозитария не обязательно. Затем я написал сценарий ant выполняющий компиляцию проекта и упаковку его в виде war-архива.
<?xml version="1.0" encoding="windows-1251"?>
<project name="joidapp" default="all" basedir=".">
<target name="init">
<property name="name" value="joidserver" />
<property name="version" value="1.0" />
<property name="out" value="out" />
<property name="src" value="src" />
<property name="lib" value="lib" />
<property name="configs" value="configs" />
<property name="examples" value="examples/server" />
<property name="tomcat" location="E:\Program_Files_2\apache-tomcat-6.0.14" />
<path id="clp">
<fileset dir="${lib}">
<include name="*.jar" />
</fileset>
</path>
</target>
<target name="clean" depends="init">
<delete dir="${out}" quiet="true" />
<mkdir dir="${out}" />
<mkdir dir="${out}/WEB-INF" />
<mkdir dir="${out}/WEB-INF/lib" />
<mkdir dir="${out}/WEB-INF/classes" />
<copy todir="${out}/WEB-INF/lib">
<fileset dir="${lib}">
<include name="**/*.jar" />
<exclude name="**/javax.servlet.jar" />
</fileset>
</copy>
<copy todir="${out}">
<fileset dir="${examples}">
<include name="**/*.*" />
</fileset>
</copy>
<copy file="${configs}/web.xml" todir="${out}/WEB-INF" />
<copy file="${src}/log4j.properties" todir="${out}/WEB-INF/lib" />
</target>
<target name="compile" depends="clean">
<javac srcdir="${src}" destdir="${out}/WEB-INF/classes" fork="true" classpathref="clp">
</javac>
</target>
<target name="makewar" depends="compile">
<jar jarfile="${out}/${name}-${version}.war">
<fileset dir="${out}" />
</jar>
<copy todir="${tomcat}/webapps" file="${out}/${name}-${version}.war" />
</target>
<target name="all" depends="makewar" />
</project>
Файл web.xml я разместил в новой папке configs и выглядит он так:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<filter>
<filter-name>OpenIdFilter</filter-name>
<filter-class>org.verisign.joid.consumer.OpenIdFilter</filter-class>
<init-param>
<description>Optional. Will store the identity url in a cookie under "openid.identity" if set to true.</description>
<param-name>saveInCookie</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenIdFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Устройство сервлета очень простое: в метод doFilter выполняется проверка двух вещей: того, что обслуживаемый адрес не попал в список "блокированных ресурсов" (настраивается в web.xml) и то, что в списке входных переменных есть одна с именем openid.identity - это признак обратного вызова от сервера аутентификации. Если оба эти условия выполняется, то процедура аутентификации завершается и помещаются сведения о ней внутрь cookie и внутрь сессии:
public static final String OPENID_ATTRIBUTE = "openid.identity";
// бла-бла-бла
req.getSession(true).setAttribute(OpenIdFilter.OPENID_ATTRIBUTE, identity);
Все приложение заработало. Пока только в режиме consumer-а. Теперь надо провести тесты на "профпригодность". Для этого я использовал тех самых openid-провайдеров, о которых писал в прошлой статье.
1. Тест с mediawiki пройден успешно.
2. Тест с wordpress провален: переход на страницу провайдера выполнен не был, вместо этого получено сообщение об ошибке " An error occurred! Please press back and try again. ". В лог tomcat-а попало сообщение, что возникла ошибка NullPointerException, но это произошло где-то внутри файла JoidConsumer.java, но вникать в суть дела и пользоваться отладичком желания у меня не было. Спасибо, следующий.
3. Тест с phpMyID (доступен по адресу http://siege.org/projects/phpMyID/). Результаты изрядно удивили. После ввода в форму адреса openid-страницы передо мной появилось окно ввода имени и пароля. Но после того как я ввел там эти данные (правильные данные), обратный переход на страницу joid выполнен не был, а вместо этого меня снова попросили ввести имя и пароль. В ходе этого на заднем фоне firefox мигало какое-то всплывающее окошко, но оно исчезало так быстро, что рассмотреть толком не успевал. После того как мне надоело вводить имя и пароль. Я отказался и : при повторной попытке (с самого начала запустить процесс openid-аунтентификации) я успешно получил сообщение, что эта процедура была пройдена успешно (сам переход на страницу провайдера уже не выполнялся). Напомнило анекдот про двух алкашей и огурец в трехлитровой банке.
4. Тест с "my openIDOO" (загружен из SVN репозитария "svn checkout http://openidoo.googlecode.com/svn/trunk/ openidoo"). Тест пройден не был: получено очень понятное сообщение об ошибке: "An error occurred! Please press back and try again".
5. Тест с "PHP OpenID Server by JanRain, Inc". Тест также не был пройден. На этот раз в отличие от предыдущих тестов поведение было другим. После ввода openid-идентификатора я попал на страницу для ввода имени и пароля, ввел их, но обратный переход на страницу joid выполнен не был.
Выводы: все ужасно, только mediawiki не завалила тест.
Теперь попробую рассмотреть код клиентской части joid (в глубине души теплится надежда, что возможно я "просто не умею готовить сервера openid").
String returnTo = UrlUtils.getBaseUrl(request);
if (request.getParameter("signin") != null) {
String id = request.getParameter("openid_url");
if (!id.startsWith("http:")) {
id = "http://" + id;
}
String trustRoot = returnTo;
String s = OpenIdFilter.joid().getAuthUrl(id, returnTo, trustRoot);
response.sendRedirect(s);
}
Следующий шаг - проверка, вдруг процедура аутентификации уже была пройдена и тогда извлекается имя пользователя и печатается на странице:
String loggedInAs = OpenIdFilter.getCurrentUser(session);
В целом впечатление от клиентской части библиотеки очень положительное: код действительно компактен и прост. Хотя от необходимости "поработать напильником" я не свободен. В библиотеке реализована возможность выполнять запросы с помощью SRE (Simple Registration Extension) с целью получения таких сведений как nickname, fio, emai, : Так вот, используя только методы сервлета OpenIdFilter сделать это не возможно, нужно вносить правки в код класса JoidConsumer (именно это класс выполняет черновую работу) и изменить методы создания запроса на аутентификацию. С другой стороны библиотека находится в состоянии развития так что ...
Про сервер
Пример сервера joid построен с помощью трех файлов: login.jsp, me.jsp, logout.jsp. Их назначение, соответственно, логин совмещенный с созданием пользователей, затем, персональная страница аутентифицированного пользователя и страница выхода. Скажу сразу использовать этот пример как openid-сервер не возможно: продукт крайне сырой, нет достаточной документации, идущий в примере код сервлета-сервера openid (работает только с хранящимися в памяти данными), попытки привязать источник данных взятый из базы данных натолкнулся на отстуствие документации по использованию класса dbStore, а из названий и параметров методов нельзя было определить как указать ту БД, таблицу (и как она должна выглядеть). Вывод: фтоппку.
« Заметки про java и загрузку файлов с помощью commons fileupload | Hessian связывает flash и java » |