Search code examples
grailsspring-security

Grails Spring Security Shiro, how to create 2 login forms with 2 different authentication success urls?


I am working a project that leverages Spring Security Shiro. I would like to configure the application to have 2 different login forms with 2 different authentication success urls. What is the best way to perform this? I looked at the documentation but have not seen any solutions.

Thank you in advance for your help.


Solution

  • The simple way was to override the AuthenticationSuccessHandler with a custom one.

    First create your success handler, my checks to see if the user is an admin user.

    import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
    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 CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    
        def requestCache
        boolean administrator = false
    
        @Override
        protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
            println administrator
            if(administrator){
                return "/admin"
            } else {
                return super.determineTargetUrl(request, response)
            }
        }
    
        @Override
        public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
                                            final Authentication authentication) throws ServletException, IOException {
            try {
                checkSetAdministratorUser(authentication)
                handle(request, response, authentication)
                super.clearAuthenticationAttributes(request)
            }catch(Exception e){
                e.printStackTrace()
            } 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)
        }
    
        def checkSetAdministratorUser(authentication){
            authentication.authorities.each(){ authority ->
                if(authority.authority == "ROLE_ADMIN")administrator = true
            }
        }
    }
    

    Then I had to define the success handler in the beans section of resources.groovy

    beans = {
        authenticationSuccessHandler(CustomAuthenticationSuccessHandler) {
            requestCache = ref('requestCache')
            redirectStrategy = ref('redirectStrategy')
        }
    }
    

    Then I was good to go. It worked well for my scenario.

    Thanks: https://groggyman.com/2015/04/05/custom-authentication-success-handler-with-grails-and-spring-security/