簡體   English   中英

掛毯覆蓋身份驗證器

[英]Tapestry override Authenticator

我正在嘗試為掛毯安全性 ( 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);
}

但是,這會導致緩存在注銷時不會被清除 - 我懷疑這是由 Shiro 的DefaultSecurityManager檢測身份驗證器是否監聽注銷的方式引起的:

Authenticator authc = getAuthenticator();
if (authc instanceof LogoutAware) {
    ((LogoutAware) authc).onLogout(principals);
}

由於EnvironmentalRealmAuthenticator被綁定為 Tapestry 服務,它最初作為代理注入,因此authc instanceof LogoutAware產生false - 這就是默認的ModularRealmAuthenticator在 Tynamo 的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");

這導致以下異常:

Caused by: java.lang.IllegalStateException: 由於遞歸,服務“ServiceOverride”的構建失敗:服務以某種方式依賴於自身。 Please check org.apache.tapestry5.ioc.internal.services.ServiceOverrideImpl(Map) (at ServiceOverrideImpl.java:31) via org.apache.tapestry5.ioc.modules.TapestryIOCModule.bind(ServiceBinder) (at TapestryIOCModule.java:52 ) 引用另一個本身依賴於服務“ServiceOverride”的服務。

如果沒有看到導致該異常的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);
}

我似乎找到了一種(相當古怪的)方法。 我沒有覆蓋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而不必實際覆蓋它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM