Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF with Spring security - Redirect to specified page after login

I have a web application which uses JSF and Spring security is used for login and authorization.

When a user types in a specific page and he is not logged in, e.g. localhost:8080/APP/page.xhtml, the application redirects to the login page which is OK. After that, the user is logged in but the page he is redirected to is index.xhtml which is the default welcome page, and not to page.xhtml.

I want the following behaviour: user goes to localhost:8080/APP/page.xhtml, he is redirected to be logged in and after that he should be redirected to his desired page - page.xhtml.

Edited - Snippet of spring-security.xml:

 <security:http auto-config="true">
    <security:intercept-url pattern="/javax.faces.resource/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <security:intercept-url pattern="/login.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

    <security:intercept-url pattern="/**" access="ROLE_UNALLOCATED, ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/management/" access="ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/requests/" access="ROLE_UNALLOCATED, ROLE_EMPLOYEE, ROLE_TEAM_LEADER, ROLE_MANAGER"/>

    <security:form-login login-page="/login.xhtml" 
                          />
    <security:logout logout-url="/j_spring_security_logout"
            logout-success-url="/login.xhtml"
            invalidate-session="true"/>
</security:http>

Any ideas? Thanks

Edit:

I thought it was because:

 <!-- Welcome page -->
<welcome-file-list>
    <welcome-file>/index.xhtml</welcome-file>
</welcome-file-list>

from web.xml. I removed this but with the same result.

Later edit:

I just noticed a line in my custom loginController after if (authenticationResponseToken.isAuthenticated()) which is almost surely the source of the problem:

The loginController:

@ManagedBean(name = "loginController")
@SessionScoped
@Controller
public class LoginController implements Serializable {
private static final long serialVersionUID = 1L;

@Autowired
IUserService userService;

@Autowired
@Qualifier("authenticationManager")
protected AuthenticationManager authenticationManager;

// save the current user after login to be able to inject it in other places
// as needed
private User currentUser;

/**
 * This action logs the user in and returns to the secure area.
 * 
 * @return String path to secure area
 */
public String loginUsingSpringAuthenticationManager() {
    // get backing bean for simple redirect form
    LoginFormBackingBean loginFormBean = (LoginFormBackingBean) FacesUtils
            .getBackingBean("loginFormBean");

    // simple token holder
    Authentication authenticationRequestToken = createAuthenticationToken(loginFormBean);

    // authentication action
    try {
        Authentication authenticationResponseToken = authenticationManager
                .authenticate(authenticationRequestToken);

        Authentication authCopy = null;
        final Object principal = authenticationResponseToken.getPrincipal();
        if (principal instanceof LdapUserDetailsImpl) {
            LdapUserDetailsImpl userImpl = (LdapUserDetailsImpl) principal;
            userImpl.getUsername();

            // here check if we already have a User with his DN in the DB
            // get the User by DN
            User u = userService.getUserByDn(userImpl.getDn());

            // if a user with this DN does not exist in the DB, create a new
            // one with the DN from LDAP and the default settings for a new
            // user
            if (null == u) {
                u = userService.createNewUserFromDn(userImpl.getDn(),
                        userImpl.getUsername());
            }
            // set the obtained user as the current user
            setCurrentUser(u);
            List<GrantedAuthority> grAuth = new ArrayList<GrantedAuthority>();
            // after this, do the role authority stuff
            // here loop through user roles if he has more and
            if (null != u.getUserTeamRoles()) {
                for (UserTeamRole urt : u.getUserTeamRoles()) {
                    // here get role for every UserTeamRole
                    grAuth.add(new SimpleGrantedAuthority(urt.getRole()
                            .getName()));
                }
            }

            // add the above found roles to the granted authorities of the
            // current authentication
            authCopy = new UsernamePasswordAuthenticationToken(
                    authenticationResponseToken.getPrincipal(),
                    authenticationResponseToken.getCredentials(), grAuth);
        }

        SecurityContextHolder.getContext().setAuthentication(authCopy);
        // ok, test if authenticated, if yes reroute
        if (authenticationResponseToken.isAuthenticated()) {
            // lookup authentication success url, or find redirect parameter
            // from login bean
            return "index.xhtml?faces-redirect=true";
        }
    } catch (BadCredentialsException badCredentialsException) {
        // FacesMessage facesMessage = new FacesMessage(
        // "Login Failed: please check your username/password and try again.");
        // FacesContext.getCurrentInstance().addMessage(null, facesMessage);
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        "Sample error message",
                        "Login Failed! Please check your credentials"));
    } catch (LockedException lockedException) {
        FacesMessage facesMessage = new FacesMessage(
                "Account Locked: please contact your administrator.");
        FacesContext.getCurrentInstance().addMessage(null, facesMessage);
    } catch (DisabledException disabledException) {
        FacesMessage facesMessage = new FacesMessage(
                "Account Disabled: please contact your administrator.");
        FacesContext.getCurrentInstance().addMessage(null, facesMessage);
    }

    return null;
}

private Authentication createAuthenticationToken(
        LoginFormBackingBean loginFormBean) {
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
            loginFormBean.getUserName(), loginFormBean.getPassword());
    return usernamePasswordAuthenticationToken;
}

How can I redirect to the page I need? I have a loginBean which contains the user and password and I could add a redirectUrl but how do I find the previous url path?

like image 549
AndaP Avatar asked Dec 11 '25 14:12

AndaP


1 Answers

Spring Security implements this logic for you in the AbstractAuthenticationProcessingFilter (typically using the concrete implementation of UsernamePasswordAuthenticationFilter) by using the SavedRequestAwareAuthenticationSuccessHandler (which uses the HttpSessionRequestCache under the covers). Since you have written a controller to authenticate (rather than using the built in support) you will need to implement this logic yourself. Rather than implementing all of the logic yourself, you can reuse the same classes Spring Security does.

For example, your LoginController might be updated as follows:

public class LoginController implements Serializable {
    // ... same as before ...
    private RequestCache requestCache = new HttpSessionRequestCache();

    public String loginUsingSpringAuthenticationManager() {
        // ... just as you had been doing ...

        if (authenticationResponseToken.isAuthenticated()) {
            HttpServletRequest request = (HttpServletRequest)         
              FacesContext.getCurrentInstance().getExternalContext().getRequest();
            HttpServletResponse response = (HttpServletResponse)         
              FacesContext.getCurrentInstance().getExternalContext().getResponse();

            SavedRequest savedRequest = requestCache.getRequest(request, response);

            return savedRequest.getRedirectUrl();
        }

        // ... same as you had ...
   }
}
like image 169
Rob Winch Avatar answered Dec 14 '25 11:12

Rob Winch