The reason I caught UnauthenticatedException explicitly is because that's
what gets thrown when a method is protected with @RequiresAuthetication.
Ideally, I'd like to be able to handle all exceptions thrown by any of the
@Requires* annotations.
I've tried a few permutations based on your suggestions, and I'm afraid I'm
still not understanding enough to make this work.
As an experiment, I first tried implementing my custom filter like so:
public class AuthorizationFailureFilter extends FormAuthenticationFilter {
@Override
public void afterCompletion( ServletRequest request, ServletResponse
response, Exception exception ) throws Exception {
if ( exception instanceof UnauthenticatedException || ( exception
instanceof ServletException && exception.getCause() instanceof
UnauthenticatedException ) ) {
super.onAccessDenied( request, response );
}
}
}
I kept my servlet configuration the same as in my original post. My
expectation based on my understanding of FormAuthenticationFilter is that
this should at least bounce me to the login page on an
UnauthenticatedException. However, it didn't work, and it also broke my
existing FormAuthenticationFilter (which uses path-based filtering to secure
an unrelated URL called "/secure"). In both cases, I end up with errors
related to a missing SecurityManager. The path-based filter throws this
explicitly, but the annotation-based filter swallows it in the AdviceFilter
to allow the original exeception to be propagated:
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager
accessible to the calling code, either bound to the
org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an
invalid application configuration.
I assume what's happening is that I have essentially 2 instances of
FormAuthenticationFilter floating around: the one assigned to the static
ShiroWebModule.AUTHC variable which I've added to my filter chain, and the
subclassed one--AuthorizationFailureFilter--that I assign explictly in my
Guice ServletModule. Somehow the latter instance is not getting a
SecurityManager, and that's affecting the former. I'm still trying to
understand how via the debugger.
My 2nd thought was that perhaps I should limit it to just one instance, so I
changed my ShiroWebModule like so:
public class BigBankShiroWebModule extends ShiroWebModule {
protected void configureShiroWeb() {
...
Key<AuthorizationFailureFilter> myAUTHC = Key.get(
AuthorizationFailureFilter.class );
addFilterChain( "/login.jsp", myAUTHC );
addFilterChain( "/secure/**", myAUTHC );
}
}
I then removed the explicit filter binding from my Guice ServletModule. My
thought was that as long as the filter was in the chain, it should handle
both the regular path-based failures, plus call my custom afterCompletion()
method on failures.
This worked ... sort of. It did resolve my problem with the regular
path-based authentication handling, in that hitting "/secure" again brought
me to my login page as it did with the normal FormAuthenticationFilter.
However, through debugging I noticed that the FormAuthenticationFilter code
was all being hit twice. It hits onAccessDenied(),
saveRequestAndRedirectToLogin(), and my afterCompletion() method all twice.
I'm still trying to figure out why.
Hitting the @RequiresAuthentication-annotated method never even uses the
filter. I guess even though it's in the filter chain, since the chain only
adds it for a specific path, it won't catch the exception.
I'm sure I'm going about this all the wrong way, but I still keep hitting
dead-ends.
--
View this message in context:
http://shiro-user.582556.n2.nabble.com/Handling-exceptions-thrown-by-Requires-annotations-tp6673997p6681761.html
Sent from the Shiro User mailing list archive at Nabble.com.