Reputation: 2355
i am using Spring-Security 3.1.3 with Spring 3.2.2 and Majorra 2.1.25. I don't use managed beans, but use SpringBeanFacesELResolver. So basically, i use spring for everything.
I use the following
<http auto-config="true">
<form-login login-page="/components/public/login.jsf" authentication-failure-handler-ref="customAuthenticationFailureHandler" />
<intercept-url pattern="/components/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/components/secured/**" access="ROLE_USER,ROLE_ADMIN" />
<intercept-url pattern="/**" />
<session-management>
<concurrency-control max-sessions="1" expired-url="/components/public/sessionExpired.jsf" />
</session-management>
<access-denied-handler ref="customAccessDeniedHandler" />
</http>
which works as indended, e.g. on accessing a secured page, the user is directed to the login and after the login he is brought to the requested page. If he tries to reach an admin-page, but only has ROLE_USER, he is directed to the access-denied page by my customAccessDeniedHandler
So far so good. The problem now is the following:
i use @Secured({ "ROLE_ADMIN" })
on a method. If a user with insufficient rights accesses this method, an AccessDeniedException is thrown, which is just what i want. BUT: My customAccessDeniedHandler is not invoked! Why is that?
Some more info: The method is invoked as part of an AJAX call and i would like to use my handler to set a FacesMessage as Feedback. How do i do this centrally? I am pretty sure i could wrap another method around this and use try-catch to catch the AccessDeniedException myself. But doing this for every method that has to be secured will just bloat up my code with a massive amount of unnecessary try-catch-methods. How can i handle the Exception centrally?
Upvotes: 1
Views: 930
Reputation: 2355
I found a solution now. I use Spring-AOP and "bind" an around aspect to all methods annotated with @Secured
<!-- aspect configuration -->
<aop:config>
<aop:aspect id="securedAspect" ref="securityFeedbackAspect">
<aop:around pointcut="@annotation(org.springframework.security.access.annotation.Secured)" method="handleSecuredAnnotations" />
</aop:aspect>
</aop:config>
The aspect looks like this
@Service
public class SecurityFeedbackAspect {
public Object handleSecuredAnnotations(final ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (AccessDeniedException e) {
// log + set feedback for user here
}
}
}
Hope this helps anyone someday. One addition info: Somehow i couldn't get this to work with annotation-only configuration, because the @Secured-check would always be invoked first and my aspect would only run if no exception was thrown by the Spring-Security-Logic. I ended up using XML configuration, which seems to always go first, since i found no other way (even with @Order)
Upvotes: 1