It’s Sunday and instead of devoting this day to our Lord I will dedicate it to the great Machine and its coding brethren. The jokes aside, this is a quick show up of how to establish custom Authentication Success Handler if you are working with Grails Framework + Spring Security Core Plugin.
Well first, why would you need to alter the ‘normal’ behaviour of the handler?
The answer: let’s say, you want to change the targetUrl for the specific authenticated user. Is that not enough? 🙂
HOW TO DO IT
With Spring and Java what you need to do is to implement the AuthenticationSuccessHandler interface. It has only one method to be implemented:
void onAuthenticationSuccess(HttpServletRequest var1, HttpServletResponse var2, Authentication var3);
With Grails and Spring Security Core plugin we follow the same path, just the ritual is a little bit different.
Spring Security Plugin use the AjaxAwareAuthenticationSuccessHandler bean that extends SavedRequestAwareAuthenticationSuccessHandler and if you follow the hierarchy tree you will notice that at some point the needed interface is implemented at the upper classes. So what we need to do is just extend AjaxAwareAuthenticationSuccessHandler and define the bean in resources.groovy (оr .xml).
package com.wordpress.groggystuff.grails import grails.plugin.springsecurity.web.authentication.AjaxAwareAuthenticationSuccessHandler import org.springframework.security.core.Authentication import javax.servlet.ServletException import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import javax.servlet.http.HttpSession class GroggySuccessHandler extends AjaxAwareAuthenticationSuccessHandler { boolean userIsBadPerson = false @Override protected String determineTargetUrl(HttpServletRequest request,HttpServletResponse response) { if(userIsBadPerson){ logger.info("This user is very nasty. Send him to /dev/null to rot.") return "/dev/null" } else { return super.determineTargetUrl(request, response) } } @Override public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws ServletException, IOException { try { checkIfTheUserIsBadPerson(request.getSession(),authentication) handle(request,response,authentication) super.clearAuthenticationAttributes(request) } finally { // always remove the saved request requestCache.removeRequest(request, response) } } protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { String targetUrl = determineTargetUrl(request, response) if (response.isCommitted()) { logger.debug("Response has already been committed. Unable to redirect to " + targetUrl) return } redirectStrategy.sendRedirect(request, response, targetUrl) } private void checkIfTheUserIsBadPerson(HttpSession session, Authentication authentication){ // do the groggy check to find if the user is a bad person // presume that the user is always a bad person userIsBadPerson = true } }
When the user authenticates successfully onAuthenticationSuccess
method is called. With this code the method determineTargetUrl will be always referenced when the user logins and from there we can easily change the targetUrl that the handle method redirects to. I wrote a logical check with which I check when to redirect and how to build my targetUrl in determineTargetUrl. Don’t forget to define the bean in resources.groovy . The bean id must be the same as in the plugin, otherwise this class will be just ignored.
beans = { // other beans authenticationSuccessHandler(GroggySuccessHandler) { /* Reusing the security configuration */ def conf = SpringSecurityUtils.securityConfig /* Configuring the bean */ requestCache = ref('requestCache') redirectStrategy = ref('redirectStrategy') defaultTargetUrl = conf.successHandler.defaultTargetUrl alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault targetUrlParameter = conf.successHandler.targetUrlParameter ajaxSuccessUrl = conf.successHandler.ajaxSuccessUrl useReferer = conf.successHandler.useReferer } }
And that’s it my lads and gals. (tested with Grails 2.5.0 and spring-security-core:2.0-RC4)
And a song as always.
Nice explanation
LikeLike