Гобелен переопределяет аутентификатор

Я пытаюсь использовать собственный аутентификатор для безопасности гобелена (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);
}
Другие вопросы по тегам