Ни для кого не секрет что сервера приложений существуют для того чтобы снять некоторую часть работы с разработчика и возложить её на уже готовые механизмы. В частности механизм аутентификации в сервере приложений Glassfish можно организовать с помощью так называемых Security Realms. Существуют несколько встроенных вариантов, такие как аутентификация через СУБД, LDAP, PAM, Certificate и обычное чтение из файла. Однако они могут нас не устроить ввиду своей ограниченности (LDAP, например, может работать только с одним наперед заданным доменом). Поэтому мы и рассмотрим создание собственного security realm’а.
Custom security realm состоит минимум из двух классов. Один из которых расширяет класс AppservRealm (com.sun.appserv.security.AppservRealm), а второй соответственно AppservPasswordLoginModule (com.sun.appserv.security.AppservPasswordLoginModule). Для получения com.sun.appserv.security.* нужно импортировать в качестве библиотеки /glassfish/modules/security.jar
В классе realm'а необходимо переопределить методы получения типа аутентификации (обычно это название realm'а) и получение групп пользователя по его имени — в данной статье мы умышленно упускаем обзор Java EE авторизации.
Соответственно здесь мы и можем реализовать гибкость механизма в получении групп по имени пользователя, например из СУБД. В данном примере используется одна группа, которая показывает что пользователь прошел аутентификацию. Property jaas-context указывается здесь чтобы связать данный класс со следующим.
В данном классе необходимо реализовать метод аутентификации. Он состоит из получения и проверки использующего его realm'а, проверки правильности введенных логина и пароля (либо других реквизитов) и наконец, получения и передачи групп пользователя.
Скомпилированные классы (пакеты с соответствующими классами внутри) кладем в директорию <домен glassfish>/lib/classes
Также мы должны определить что наш AppservPasswordLoginModule относится к определенному контексту. Нужно отредактировать файл <домен glassfish>/config/login.conf добавив «ссылку»:
В котором мы определяем контекст и ссылаемся на необходимость модуля.
Смело запускаем/перегружаем наш сервер приложений и открываем GUI администратора.
Создаем новый Security Realm. Теперь нам не нужно выбирать класс из списка, а вводим полный класс реалма: ru.khmb.security.Realm. Не забываем указать опцию jaas-context которая связывает наш realm с модулем аутентификации через контекст указанный в файле login.conf, т.е. в нашем случаи jaas-context = KHMBRealm
Всё, теперь можно пользоваться Realm'ом.
При реализации механизма источником была запись в блоге.
Update 02.08.2013:
Есть хорошее описание создания различных Security Realm'ом (областей безопасности) в книге Дэвида Хеффельфингера «Java EE 6 и сервер приложений GlassFish 3»
Custom security realm состоит минимум из двух классов. Один из которых расширяет класс AppservRealm (com.sun.appserv.security.AppservRealm), а второй соответственно AppservPasswordLoginModule (com.sun.appserv.security.AppservPasswordLoginModule). Для получения com.sun.appserv.security.* нужно импортировать в качестве библиотеки /glassfish/modules/security.jar
package ru.khmb.security;
import com.sun.appserv.security.AppservRealm;
import com.sun.enterprise.security.auth.realm.BadRealmException;
import com.sun.enterprise.security.auth.realm.InvalidOperationException;
import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
import com.sun.enterprise.security.auth.realm.NoSuchUserException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
public class Realm extends AppservRealm {
private static final String PARAM_JAAS_CONTEXT = "jaas-context";
private static final String GROUP_ALL = "Authenticated";
@Override
public void init(Properties properties)
throws BadRealmException, NoSuchRealmException {
String propJaasContext = properties.getProperty(PARAM_JAAS_CONTEXT);
if (propJaasContext != null) {
setProperty(PARAM_JAAS_CONTEXT, propJaasContext);
}
}
@Override
public String getAuthType() {
return "KHMB Realm";
}
@Override
public Enumeration getGroupNames(String user)
throws InvalidOperationException, NoSuchUserException {
Vector vector = new Vector();
vector.add(GROUP_ALL);
return vector.elements();
}
}
В классе realm'а необходимо переопределить методы получения типа аутентификации (обычно это название realm'а) и получение групп пользователя по его имени — в данной статье мы умышленно упускаем обзор Java EE авторизации.
Соответственно здесь мы и можем реализовать гибкость механизма в получении групп по имени пользователя, например из СУБД. В данном примере используется одна группа, которая показывает что пользователь прошел аутентификацию. Property jaas-context указывается здесь чтобы связать данный класс со следующим.
package ru.khmb.security;
import com.sun.appserv.security.AppservPasswordLoginModule;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import javax.security.auth.login.LoginException;
public class LoginModule extends AppservPasswordLoginModule {
@Override
protected void authenticateUser() throws LoginException {
if (!(_currentRealm instanceof Realm)) {
throw new LoginException("Realm not KHMBRealm");
}
Realm realm = (Realm) _currentRealm;
authenticate(_username, _password);
Enumeration enumeration = null;
List<String> authenticatedGroups = new LinkedList();
try {
enumeration = realm.getGroupNames(_username);
} catch (Exception e) {
throw new LoginException("Get groups exception");
}
for (int i = 0; enumeration != null && enumeration.hasMoreElements(); i++) {
authenticatedGroups.add((String) enumeration.nextElement());
}
commitUserAuthentication(authenticatedGroups.toArray(new String[0]));
}
private static void authenticate(String login, String password) throws LoginException {
try {
LDAP.authenticate(login, password);
} catch (Exception e) {
throw new LoginException("Authenticate exception:" + e.getMessage());
}
}
}
В данном классе необходимо реализовать метод аутентификации. Он состоит из получения и проверки использующего его realm'а, проверки правильности введенных логина и пароля (либо других реквизитов) и наконец, получения и передачи групп пользователя.
Скомпилированные классы (пакеты с соответствующими классами внутри) кладем в директорию <домен glassfish>/lib/classes
Также мы должны определить что наш AppservPasswordLoginModule относится к определенному контексту. Нужно отредактировать файл <домен glassfish>/config/login.conf добавив «ссылку»:
KHMBRealm {
ru.khmb.security.LoginModule required;
};
В котором мы определяем контекст и ссылаемся на необходимость модуля.
Смело запускаем/перегружаем наш сервер приложений и открываем GUI администратора.
Создаем новый Security Realm. Теперь нам не нужно выбирать класс из списка, а вводим полный класс реалма: ru.khmb.security.Realm. Не забываем указать опцию jaas-context которая связывает наш realm с модулем аутентификации через контекст указанный в файле login.conf, т.е. в нашем случаи jaas-context = KHMBRealm
Всё, теперь можно пользоваться Realm'ом.
При реализации механизма источником была запись в блоге.
Update 02.08.2013:
Есть хорошее описание создания различных Security Realm'ом (областей безопасности) в книге Дэвида Хеффельфингера «Java EE 6 и сервер приложений GlassFish 3»