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