Гобелен переопределяет аутентификатор
Я пытаюсь использовать собственный аутентификатор для безопасности гобелена (org.tynamo.security).
У меня есть кастомный аутентификатор
public class EnvironmentalRealmAuthenticator extends ModularRealmAuthenticator
И в моем модуле я отменяю аутентификатор по умолчанию для Tapestry (ModularRealmAuthenticator
):
public static void bind(final ServiceBinder binder) {
binder.bind(Authenticator.class, EnvironmentalRealmAuthenticator.class).withId("EnvironmentalRealmAuthenticator");
}
@Contribute(ServiceOverride.class)
public static void setupOverrides(final MappedConfiguration<Class, Object> configuration, @Local final Authenticator override) {
configuration.add(Authenticator.class, override);
}
Однако это приводит к тому, что кеш не очищается при выходе из системы - у меня есть подозрение, что это вызвано тем, как
DefaultSecurityManager
Широ определяет, прослушивает ли аутентификатор выход из системы:
Authenticator authc = getAuthenticator();
if (authc instanceof LogoutAware) {
((LogoutAware) authc).onLogout(principals);
}
Как
EnvironmentalRealmAuthenticator
привязан как сервис Tapestry, он изначально вводится как прокси и, следовательно,
authc instanceof LogoutAware
дает
false
- поэтому по умолчанию
ModularRealmAuthenticator
связан по-другому в
SecurityModule
Тинамо:
// TYNAMO-155 It's not enough to identify ModularRealmAuthenticator by it's Authenticator interface only
// because Shiro tests if the object is an instanceof LogoutAware to call logout handlers
binder.bind(ModularRealmAuthenticator.class);
Однако, когда я пытаюсь переопределить
EnvironmentalRealmAuthenticator
сюда
binder.bind(EnvironmentalRealmAuthenticator.class).withId("EnvironmentalRealmAuthenticator");
это приводит к следующему исключению:
Вызвано: java.lang.IllegalStateException: создание службы ServiceOverride не удалось из-за рекурсии: служба каким-то образом зависит от себя. Проверьте org.apache.tapestry5.ioc.internal.services.ServiceOverrideImpl(Map) (на ServiceOverrideImpl.java:31) через org.apache.tapestry5.ioc.modules.TapestryIOCModule.bind(ServiceBinder) (на TapestryIOCModule.java:) для ссылок на другую службу, которая сама зависит от службы ServiceOverride.
2 ответа
Кажется, я нашел (довольно хакерский) способ. Вместо того, чтобы игнорировать
Authenticator
сам я отменяю
WebSecuritymanager
вместо:
public static void bind(final ServiceBinder binder) {
binder.bind(EnvironmentalRealmAuthenticator.class).withId("EnvironmentalRealmAuthenticator");
binder.bind(WebSecurityManager.class, EnvironmentalSecurityManager.class).withId("EnvironmentalSecurityManager");
}
@Contribute(ServiceOverride.class)
public static void setupOverrides(final MappedConfiguration<Class, Object> configuration, @Local final WebSecurityManager override) {
configuration.add(WebSecurityManager.class, override);
}
Таким образом, мне не нужно связывать
EnvironmentalRealmAuthenticator
со своим интерфейсом. Чтобы иметь возможность идентифицировать новый
Authenticator
Я аннотировал модуль:
@Marker(Primary.class)
Внедрение
EnvironmentalSecurityManager
то выглядит так:
/**
* Used to properly (and uniquely) identify the authenticator (without having to override it)
*/
public class EnvironmentalSecurityManager extends TapestryRealmSecurityManager {
private final Logger logger = LoggerFactory.getLogger(EnvironmentalSecurityManager.class);
/**
* Mind the @Primary annotation, used to identify the EnvironmentalRealmAuthenticator
*/
public EnvironmentalSecurityManager(final @Primary Authenticator authenticator, final SubjectFactory subjectFactory, final RememberMeManager rememberMeManager, final Collection<Realm> realms) {
super(authenticator, subjectFactory, rememberMeManager, realms);
logger.debug("Created EnvironmentalSecurityManager - class of authenticator is {}", authenticator.getClass());
}
}
Таким образом, я могу гарантировать, что правильный
Authenticator
используется без необходимости его отмены.
Я не могу быть уверенным, не увидев окончательную версию вашего
setupOverrides
метод, вызвавший это исключение.
Но пробовали ли вы это:
public static void bind(final ServiceBinder binder) {
binder.bind(EnvironmentalRealmAuthenticator.class);
}
@Contribute(ServiceOverride.class)
public static void setupOverrides(final MappedConfiguration<Class, Object> configuration, EnvironmentalRealmAuthenticator override) {
configuration.add(Authenticator.class, override);
}