Search code examples
authenticationstruts2spring-securityauthorizationj-security-check

determine target url based on roles for struts2


I am new to struts and spring security. Can anyone help me to figure out how to redirect to different urls different users with different roles ? In other words, how to provide determine target url based on user role in struts2 using action controller?

I found the following question determine target url based on roles in spring security 3.1 , but I cannot figure out how to configure the action.

I tried the following setup, but it does not work:

security.xml

 <form-login login-page="/login" authentication-failure-url="/login?error=true" login-processing-url="/j_security_check" default-target-url="/default"/>

struts.xml

<action name="default" class="com.moblab.webapp.action.RoleRedirectAction" method="defaultAfterLogin"/>

RoleRedirectAction.java

package com.moblab.webapp.action;
import javax.servlet.http.HttpServletRequest;
public class RoleRedirectAction extends BaseAction{

public String defaultAfterLogin(HttpServletRequest request) {
    if (request.isUserInRole("ROLE_ADMIN")) {
        return "redirect:/<url>";
    }
    return "redirect:/<url>";
}
}

Thanks a lot.

EDIT 1 I also tried the following annotation

 @Action(value="/default",results={@Result(name="success",location="/querySessions")})

EDIT 2 My final solution looks like the following. I am not sure if it is the best approach, but it works:

public class StartPageRouter extends SimpleUrlAuthenticationSuccessHandler {


@Autowired
private UserService userService;

protected final Logger logger = Logger.getLogger(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();

@Override
public void onAuthenticationSuccess(HttpServletRequest request,
                                    HttpServletResponse response,
                                    Authentication authentication) throws IOException, ServletException {


    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

    //default path for ROLE_USER
    String redirectPath = <url>;

    if (authorities != null && !authorities.isEmpty()) {

        Set<String> roles = getUserRoles(authorities);

        if (roles.contains("ROLE_ADMIN"))
            redirectPath = <url>;
        else if (roles.contains("ROLE_INSTRUCTOR"))
            redirectPath = <url>;
    }

    getRedirectStrategy().sendRedirect(request, response, redirectPath);
}

public void setRequestCache(RequestCache requestCache) {
    this.requestCache = requestCache;
}

private Set<String> getUserRoles(Collection<? extends GrantedAuthority> authorities) {

    Set<String> userRoles = new HashSet<String>();

    for (GrantedAuthority authority : authorities) {
        userRoles.add(authority.getAuthority());
    }
    return userRoles;
}
}

EDIT 3 There are even better solutions here:

http://oajamfibia.wordpress.com/2011/07/07/role-based-login-redirect/#comment-12


Solution

  • Assuming that you mean that you want to redirect users to different start pages depending on their assigned roles then you can try this. Note that I do all this outside of Struts.

    First create your own class that extends Springs SimpleUrlAuthenticationSuccessHandler and override the onAuthenticationSuccess() method. The actual redirect is performed within the onAuthenticationSuccess() method by the line getRedirectStrategy().sendRedirect(request,response,);

    So all you need is a means of substituting your own url's.

    So, for example I have

    package com.blackbox.x.web.security;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
    import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
    import org.springframework.security.web.savedrequest.RequestCache;
    
    import com.blackbox.x.entities.UserDTO;
    import com.blackbox.x.services.UserService;
    
    
    public class StartPageRouter extends SimpleUrlAuthenticationSuccessHandler {
    
    
     @Autowired
     UserService userService;
    
     @Autowired
     LoginRouter router;
    
    
     protected final Logger logger = Logger.getLogger(this.getClass());
     private RequestCache requestCache = new HttpSessionRequestCache();
    
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication) throws IOException,
            ServletException {
    
    
        requestCache.removeRequest(request, response);
    
        User user = (User) authentication.getPrincipal();
        UserDTO userDTO = userService.find(user.getUsername());
    
        getRedirectStrategy().sendRedirect(request, response, router.route(userDTO));
    }
    
    public void  setRequestCache(RequestCache requestCache) {
                this.requestCache = requestCache;
            }
    }
    

    where LoginRouter is my own class that takes the logged in user and, from the assigned roles determines which URL the user should be directed to.

    You then configure Spring Security to use your version using the

    authentication-success-handler-ref="customTargetUrlResolver"/> 
    

    and

    <beans:bean id="customTargetUrlResolver" class="com.blackbox.x.web.security.StartPageRouter"/>
    

    in your security context xml file.