tags:

views:

365

answers:

4

Short question: Is it possible to do a redirection, say when a user isn't logged in, when a page is rendered?

+2  A: 

Yes:

if(!isLoggedIn) {
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
}
Michael Bavin
Thanks :) . It would be convenient to trigger a navigation-rule but I suppose this isn't possible.
James P.
A: 

You can use a PhaseListener to specify when you want to do redirection.

Roman
+1  A: 

For that you should use a Filter.

E.g.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { 
    if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
        ((HttpServletResponse) response).sendRedirect("error.jsf"); // Not logged in, so redirect to error page.
    } else {
        chain.doFilter(request, response); // Logged in, so just continue.
    }
}

Here I assume that the User is been placed in the session scope as you would normally expect. It can be a session scoped JSF managed bean with the name user.

A navigation rule is not applicable as there's no means of a "bean action" during a normal GET request. Also doing a redirect when the managed bean is about to be constructed ain't gong to work, because when a managed bean is to be constructed during a normal GET request, the response has already started to render and that's a point of no return (it would only produce IllegalStateException: response already committed). A PhaseListener is cumbersome and overwhelming as you actually don't need to listen on any of the JSF phases. You just want to listen on "plain" HTTP requests and the presence of a certain object in the session scope. For that a Filter is perfect.

BalusC
Thumbs up. Now, I just need to tailor this so it only triggers on certain pages.
James P.
Just make those certain pages have a generic `url-pattern` and map this filter on exactly that `url-pattern` in `web.xml`. For example `/secured/*` or so.
BalusC
+1  A: 

In a PhaseListener try:

FacesContext ctx = FacesContext.getCurrentContext();
ctx.getApplication().getNavigationHandler()
     .handleNavigation(ctx, null, "yourOutcome");
Bozho
The `FacesContext` isn't available in a `Filter` yet because it runs before the `FacesServlet` kicks in.
BalusC
When does the FacesContext appear in terms of the lifecycle?
James P.
it is present during the whole lifecycle. It is not present before the FacesServlet is invoked. The FacesServlet starts the JSF lifecycle.
Bozho