Abhishek
Abhishek

Reputation: 462

Grails security plugin custom redirection

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.

Upvotes: 3

Views: 1234

Answers (4)

Abhishek
Abhishek

Reputation: 462

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.....

Upvotes: 2

mohsenmadi
mohsenmadi

Reputation: 2377

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.

Upvotes: 0

sean3838
sean3838

Reputation: 65

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
    }
}

Upvotes: 0

sean3838
sean3838

Reputation: 65

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.

Upvotes: 1

Related Questions