I managed to create a Dynamic Authentication filter that lets the user specify at runtime which authentication method to use. My approach involved the items below, and I'd appreciate any comments. Is this a "good" approach (Is there a better way to leverage the shiro framework)?

For an example, see the following on gitub:
https://github.com/bhamail/shiro-test-dan/tree/waffleAuthStrategy

specifically:
https://github.com/bhamail/shiro-test-dan/tree/waffleAuthStrategy/cacheImpl/src/main/java/waffle/shiro/dynamic


1. DynamicAuthenticationFilter extends FormAuthenticationFilter and overrides: protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

        if (isAuthTypeNegotiate(request)) {
            log.debug("using filterNegotiate");
            return filterNegotiate.onAccessDenied(request, response);
        } else {
            log.debug("using filterFormAuthc");
            return filterFormAuthc.onAccessDenied(request, response);
        }
}


2. In order to support the back and forth handshaking of the "Negotiate" authType, I also had to create a custom auth Strategy to force the NegotiateInProgress exception up the stack: DynamicAuthenticationStrategy extends FirstSuccessfulStrategy { public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t)
            throws AuthenticationException {

if (realm instanceof NegotiateAuthenticationRealm && t instanceof AuthenticationInProgressException) { // propagate exception upward as is, to signal continue is needed
            throw (AuthenticationInProgressException)t;
        }

return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
    }
}


3. The key parts of my shiro.ini setup the Realms and Filters like so:

[main]

# Setup custom AuthenticationRealm
waffleRealmSSO = com.danrollo.negotiate.waffle.NegotiateAuthenticationRealm
waffleUserPass = waffle.shiro.GroupMappingWaffleRealm
securityManager.realms = $waffleRealmSSO, $waffleUserPass
...
authcStrategy = waffle.shiro.dynamic.DynamicAuthenticationStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy

# Waffle filter
waffleFilter = waffle.shiro.dynamic.DynamicAuthenticationFilter
...

[urls]
/* = waffleFilter


Thanks!
Dan


Reply via email to