Регистрация пользователей на сайте с помощью OpenLDAP и сервлетов
Ох уж эти самописные системы учета пользователей, разрабатываемые с нуля создателями веб-сервисов. Уязвимость, немасштабируемость, нестабильность — вот лишь основные их спутники. Другое дело — проверенные методы, такие как использование OpenLDAP. К этому серверу каталогов легко привязываются системы аутентификации распространенных веб-серверов, т.е. при внедрении такой системы приходится заниматься не столько программированием, сколько администрированием. Однако записи о новых пользователях в OpenLDAP как-то должны попадать и простенькую систему для автоматизации этого процесса все-таки создать придется. Но это займет в разы меньше времени и сил, чем написание системы регистрации «с нуля».
Для начала создадим шаблон ldif-файла, в который вместо реальных данных подставит некие поля (набраны заглавными буквами):
Шаблон может быть сколь угодно сложным, главное хорошо владеть ldif-синтаксисом. В приведенном примере регистрируется не только пользователь, но и организация, к которой он принадлежит, а также подразделение менеджеров.
Теперь пишем и подключаем к веб-серверу сервлет, считывающий параметры http-запроса в переменные, затем считывающий в строку файл ldif-шаблона и выполняющий подстановки реальных данных вместо ключевых слов:
Теперь сохраним получившуюся ldif-строку во временный файл и отправим пользователю письмо со ссылкой для активизации аккаунта:
Временному файлу автоматически присваивается длинное имя, которое можно «зашить» в url ссылки для активизации, при необходимости удлинив с помощью какого-нибудь хэш-алгоритма.
При переходе пользователя по ссылке происходит следующее.
Здесь cabinet.cgi — адрес персонального кабинета пользователя, защищенный логином/паролем на уровне веб-сервера, т.е. при переходе по этому адресу аутентификация производится стандартными средствами сервера и браузера, изобретать ничего не надо. Естественно, что обмен данными должен вестись по протоколу https.
Для начала создадим шаблон ldif-файла, в который вместо реальных данных подставит некие поля (набраны заглавными буквами):
dn: o=ORG_ID,dc=example,dc=ru
objectclass: top
objectclass: organization
o: ORG_ID
description: ORG_DESCR
dn: ou=managers,o=ORG_ID,dc=example,dc=ru
objectclass: top
objectclass: organizationalUnit
ou: managers
dn: uid=MANAGER_ID,ou=managers,o=ORG_ID,dc=gps-finder,dc=ru
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn:COMMON_NAME
gn: Undefined
sn: Undefined
mail:MAIL
userPassword: PASSWD
uid: MANAGER_ID
Шаблон может быть сколь угодно сложным, главное хорошо владеть ldif-синтаксисом. В приведенном примере регистрируется не только пользователь, но и организация, к которой он принадлежит, а также подразделение менеджеров.
Теперь пишем и подключаем к веб-серверу сервлет, считывающий параметры http-запроса в переменные, затем считывающий в строку файл ldif-шаблона и выполняющий подстановки реальных данных вместо ключевых слов:
String org = req.getParameter("orgName");
String cn = req.getParameter("commonName");
String mail = req.getParameter("mail");
String passwd = req.getParameter("passwd");
String man = req.getParameter("manager");
// проверка данных на целостность и корректность
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// считывание файла в байтовый поток, код не приводится
String ldif = new String(baos.toByteArray());
ldif = ldif
.replaceAll("ORG_ID", org)
.replaceAll("MANAGER_ID", man)
.replaceAll("COMMON_NAME", cn)
.replaceAll("PASSWD", passwd)
.replaceAll("MAIL", mail);
Теперь сохраним получившуюся ldif-строку во временный файл и отправим пользователю письмо со ссылкой для активизации аккаунта:
File tmpf = File.createTempFile("example-site-", ".ldif");
FileOutputStream fos = new FileOutputStream(tmpf);
fos.write(ldif.getBytes("UTF8"));
fos.flush();
fos.close();
// механизм отправки письма не приводится, о нем в другой раз
Временному файлу автоматически присваивается длинное имя, которое можно «зашить» в url ссылки для активизации, при необходимости удлинив с помощью какого-нибудь хэш-алгоритма.
При переходе пользователя по ссылке происходит следующее.
File tmpf = new File("/tmp/sample-site-" + p + ".ldif");
String[] sa = ("ldapadd -x -D cn=Admin,dc=example,dc=ru -w secret -f " + tmpf.getAbsolutePath()).split(" ");
Runtime.getRuntime().exec(sa);
res.setStatus(res.SC_MOVED_TEMPORARILY);
res.setHeader("Location", "cabinet.cgi");
Здесь cabinet.cgi — адрес персонального кабинета пользователя, защищенный логином/паролем на уровне веб-сервера, т.е. при переходе по этому адресу аутентификация производится стандартными средствами сервера и браузера, изобретать ничего не надо. Естественно, что обмен данными должен вестись по протоколу https.

Комментарии (4)
RSS свернуть / развернутьMarkony
Sergei_T
Как видишь, камрад, я в последнее время научился ценить решения в стиле quick&dirty. Произошло это после того, как увидел одно объявление, где умение так работать выдвигалось в качестве требования к соискателю. И все-таки есть грань. Одно дело, когда quick&dirty работает новичок и плодит кучки неуправляемого кода, другое — когда в этом стиле работает человек опытный, который тратит несколько миллионов лишних тактов процессора, но экономит себе пару часов жизни (плюс знает при этом как нужно было бы сделать правильно). Это как черный в смысле инфракрксный и черный в смысле ультрафиолетовый.
yababay
Что уж тут говорить, сам прибегаю к костыльным решениям, но со временем стараюсь заменить их на нормальные.
Sergei_T
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.