Here is my use cases.
I have a login page which is /public/login.xhtml. All my other pages are required to log-in before reaching them. They are in /pages/ directory.
I want that :
- If my user access to
http://host/myapp/pages/*it redirects him first to the login page, and then, to the URL he has firstly entered. - If my user access to
http://host/myapp/, it redirects him first to the login page, and then, to/pages/home.xhtml. - If my user access to
http://host/myapp/public/login.xhtml, it redirects him first to the login page, and then, to/pages/home.xhtml. - If my user access to
http://host/myapp/public/login.xhtmland is already logged in, it redirects to/pages/home.xhtml.
What is working currently?
With Seam 3 (v3.1.0.Final) and the Security + Faces module, my use case n°1 is automagically working with :
@ViewConfig
public interface PagesConfig {
static enum Pages {
@ViewPattern("/pages/*")
@LoginView("/public/login.xhtml")
@LoggedIn
LOGGED_IN_PAGES,
}
}
My problem is that I don’t understand how Seam’s working to do that redirection to the “capture view”.
With Seam 2, it was easy to understand, in components.xml we had
<event type="org.jboss.seam.security.notLoggedIn">
<action execute="#{redirect.captureCurrentView}" />
</event>
<event type="org.jboss.seam.security.loginSuccessful">
<action execute="#{redirect.returnToCapturedView}" />
</event>
So we captured the events notLoggedIn and loginSuccessful to handle that with a redirect component.
In Seam 3, I didn’t found that configuration : nothing seems to @Observes LoggedInEvent, and there is no Redirect class…
The point n°2 is achieved with that /index.htm file :
<html><head>
<meta http-equiv="Refresh" content="0; URL=pages/home.xhtml">
</head></html>
But for my point n°3, I’ve tried solutions which don’t fully work.
First I tried that in login.xhtml :
<f:metadata>
<s:viewAction action="#{loginAction.redirectToHome}" if="#{identity.loggedIn}" immediate="true" />
</f:metadata>
And with or without onPostback="true", after I login, I’m still in the login page with that error message (twice) : “Unable to find matching navigation case with from-view-id «/public/login.xhtml» for action «#{identity.login}» with outcome «success».“. It’s only if I now re-access to http://host/myapp/public/login.xhtml that my viewAction redirects me to the home.
I also tried that navigation-rule in faces-config.xml :
<navigation-rule>
<from-view-id>/public/login.xhtml</from-view-id>
<navigation-case>
<if>#{identity.loggedIn}</if>
<to-view-id>/pages/home.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
But then, my use case n°1 was disabled : every time I logged-in, I was redirected to the home.
Finally, for my point n°4, the s:viewAction does the job.
So does somebody knows the best practices in order to correctly handle those 4 use cases (which I think are common use cases), especially the point n°3?
Finally here is what I did.
So I removed the
if="#{identity.loggedIn}"in order to call myredirectToHomemethod which redirects tothe
/pages/home.xhtml.@ViewConfigHere is the
loginAction:The problem I faced then was when I logged out.
Here is my logout action :
And the
securityAction.logout()method :The problem is that I was redirected to the login page (thanks to the @ViewConfig I think), but no
PreLoginEventwere thrown, so the SeamLoginListener.observePreLoginEventwasn’t called, and so my previous URL wasn’t put in session. So when I logged in (immediatly after logout), I was stuck on the login page, but was logged in.Thanks to Brian Leathem and he’s previous answer, here is what I did : in my
authenticatemethod of myBaseAuthenticator, I called that method after authentication :With that solution, my previous URL wasn’t set in session, but at least, my user is redirected to the home page.