3

I am new to Groovy and Grails. I have developed an application using the Spring Security plugin using a database requested request map. I want a custom redirection to the home pages according to the roles.

If the user is ROLE_ADMIN he would be redirected to his home page in views adminUser/Homepage.gsp

If the user is ROLE_USER he would be redirected to his home page in views User/Homepage.gsp

I am not able to get any custom authentication redirection according to the user login.

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
Abhishek
  • 452
  • 3
  • 19
  • injecting springSecurityService is giving a null pointer exception below is the code and error message – Abhishek Apr 17 '15 at 10:00

4 Answers4

2
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import grails.plugin.springsecurity.SpringSecurityUtils

public class MyAuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler 
{   
    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) 
    {
        def returnUrl = request.getSession().getAttribute('returnUrl')

        def roles = SpringSecurityUtils.getPrincipalAuthorities()

        for (String role in roles)
        {            
            if (role.equals("ROLE_ADMIN")) {
                returnUrl = '/AdminUser/index.gsp'
            }
            else if (role.equals("ROLE_USER")) {
                returnUrl = '/User/index.gsp'
            }
            else {
                returnUrl = '/'
            }
        }

        request.getSession().removeAttribute('returnUrl')

        return returnUrl
    }
}

Here is my working code.... rather injecting a dependency I used SpringSecurityUtils for getting the current user role and redirecting it to the desired page...... thanks all for your support.

@sean3838 thanks for helping me out.....

Abhishek
  • 452
  • 3
  • 19
1

This is how I do it. I've modified it for your needs. Let me know if it helps.

Inside springsecurities LoginController under the auth() method do something like this (it will get the page the user was on before clicking login):

def auth() {

    session['returnUrl'] = request.getHeader("Referer")

    def config = SpringSecurityUtils.securityConfig

    if (springSecurityService.isLoggedIn()) {
        redirect uri: config.successHandler.defaultTargetUrl
        return
    }

    String view = 'auth'
    String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
    render view: view, model: [postUrl: postUrl,
                               rememberMeParameter: config.rememberMe.parameter]
}

Now inside src/groovy create an auth success handler:

package packageName

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

public class MyAuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler 
{
    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) 
    {
        def returnUrl = request.getSession().getAttribute('returnUrl')

        // Get current users role using springSecurityService
        // You can inject springSecurityService into this class
        // http://stackoverflow.com/questions/6467167/how-to-get-current-user-role-with-spring-security-plugin

        if (role == 'ROLE_ADMIN')
        {
            returnUrl = '/adminUser/Homepage.gsp'
        }
        else if (role == 'ROLE_USER')
        {
            returnUrl = '/User/Homepage.gsp'
        }
        else
        {
            returnUrl = 'redirect somewhere'
        }

        request.getSession().removeAttribute('returnUrl')

        return returnUrl
    }
}

Now under conf/spring/resources.groovy create a bean like so:

import grails.plugin.springsecurity.SpringSecurityUtils

// Place your Spring DSL code here
beans = {
    authenticationSuccessHandler(packageName.MyAuthSuccessHandler) {
        def conf = SpringSecurityUtils.securityConfig      
        requestCache = ref('requestCache')
        defaultTargetUrl = conf.successHandler.defaultTargetUrl
        alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
        targetUrlParameter = conf.successHandler.targetUrlParameter
        useReferer = conf.successHandler.useReferer
        redirectStrategy = ref('redirectStrategy')
    }
}

Then you should be good to go. Let me know if it works.

sean3838
  • 65
  • 8
0

You have to inject springSecurityService before your method. Also, getAuthorities() should return a list so you'll have to loop through it (this is because people can have more than one role).

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

public class MyAuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler 
{
    def springSecurityService

    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) 
    {
        def returnUrl = request.getSession().getAttribute('returnUrl')

        def roles = springSecurityService.getPrincipal().getAuthorities()

        for (role in roles)
        {
            if (role == 'ROLE_ADMIN')
            {
                returnUrl = '/adminUser/Homepage.gsp'
            }
            else if (role == 'ROLE_USER')
            {
                returnUrl = '/User/Homepage.gsp'
            }
        }

        request.getSession().removeAttribute('returnUrl')

        return returnUrl
    }
}
sean3838
  • 65
  • 8
  • Thanks a lot for ur help bt the problem is still the same it is again returning null..... springSecurityService is not being initialized and it is getting a nullpointer exception..... below is my error code : - [ERROR MESSAGE] Message: Cannot invoke method getPrincipal() on null object – Abhishek Apr 20 '15 at 03:58
0

Assuming you have a line like this in your BuildConfig:

    compile ":spring-security-core:2.0-RC4"

and some code like this in your BootStrap:

    def roleAdmin = new Role(authority:LSSRole.ROLE_ADMIN.toString()).save(failOnError: true)
    def roleFirm = new Role(authority:LSSRole.ROLE_FIRM.toString()).save(failOnError: true)
    def roleLaw = new Role(authority:LSSRole.ROLE_LAWYER.toString()).save(failOnError: true)
    def roleFin = new Role(authority:LSSRole.ROLE_FINANCE.toString()).save(failOnError: true)

with a sample admin user created with this code:

    UserRole.create admin, roleAdmin, true

and some code like this in Config:

'/dbconsole/**':                     [LSSRole.ROLE_ADMIN.toString()],
'/secure/**':                        [LSSRole.ROLE_ADMIN.toString()],
'/payment/**':                       [LSSRole.ROLE_FIRM.toString()],
'/filing/**':                        [LSSRole.ROLE_FIRM.toString()],
'/finance/**':                       [LSSRole.ROLE_FINANCE.toString()],
'/lawyer/**':                        [LSSRole.ROLE_LAWYER.toString()],

where LSSRole is an enum, and some code like this:

        "/" {
            controller = "dispatch"
            action = "index"
        }

in your UrlMappings to divert users to after a successful login, you can build a dispatcher like this to dispatch users to different landing pages based on their roles:

class DispatchController {

def index() { 

    def controller = 'login'
    def action = 'auth'

    if (SpringSecurityUtils.ifAllGranted(LSSRole.ROLE_ADMIN.toString())) {
        controller = 'secure'
        action = 'index' 
    } else if (SpringSecurityUtils.ifAllGranted(LSSRole.ROLE_FINANCE.toString())) { 
        controller = 'finance'
        action = 'index' 
    } else if (SpringSecurityUtils.ifAllGranted(LSSRole.ROLE_FIRM.toString())) { 
        controller = 'filing'
        action = 'summary' 
    } else if (SpringSecurityUtils.ifAllGranted(LSSRole.ROLE_LAWYER.toString())) { 
        controller = 'lawyer'
        action = 'index' 
    } else {
        flash.message = 'Where do you think you\'re going? Nno no no'
        SecurityContextHolder.clearContext()
    }

    redirect controller:controller, action:action
}

Hope this helps.

mohsenmadi
  • 2,277
  • 1
  • 23
  • 34
  • Note that with this approach in the DispatcherController, there is no need for an explicit dependency injection of springSecurityService, it works as is. – mohsenmadi Apr 17 '15 at 23:35
  • thanks a lot for your answer it is a good approach for redirection.....but my scenario is a bit different your logic cant be combined in my application.... – Abhishek Apr 20 '15 at 04:37