I think I have a correctly configured application that acts as intended.
Using standard icepush jars has the problems Evgheni has described in conjunction with Spring. Using EPS in this case allows the polling requests from the client to be handled outside the spring applications context, which allows the session to expire normally.
The other thing about the existing Spring Security tutorial is its use of xhtml pages with jsf extensions. It appears that when the application navigates to one of these pages, the EPS poll for updates operates. The application will work properly if the content with the .xhtml (the JSF content) is the only content accessed when the user is logged in.
I've created three pages with a .html extension (could be .jsp as well ) that is accessible to the user when the user is not logged in.
welcome.html A page for the user to land on when first accessing the application. This used to be main.xhtml (.jsf) and as such would start the icepush listen requests when visited, hence the session expiry messages prior to the user logging in. That behaviour is undesireable although it must be stated that it's not an error nor is it unexpected. The visitor to many shopping sites creates a Session object for shopping carts prior to logging in to make a purchase.
In the tutorial, this unsecured welcome page can represent any number of pages.
loginFailed.html - a page to land on when a login attempt fails.
formLogin.html - a page with simple form based login with fields named to Springs login standards.
sessionExpired.html - a page to land on when the session expires.
Here's the full version of applicationContext-security.xml. The changes to this file are twofold:
1) rename every .jsf page to a corresponding .html version in the /general/logins/ directory
2) Add the following line to the form-login tag:
default-target-url="/main.jsf"
<http realm="Sample Realm" entry-point-ref="authenticationEntryPoint" auto-config="false">
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<!-- any role that is used to protect a directory, can be multiples -->
<intercept-url pattern='/secure/**' access='ROLE_READER' />
<!-- enable form login to use UsernamePasswordAuthenticationFilter [/j_spring_security_check] -->
<form-login login-page="/general/logins/formLogin.html"
authentication-failure-url="/general/logins/loginFailed.html"
default-target-url="/main.jsf" />
<!-- logout page uses the default LogoutFilter, no changes are needed as IT accepts a GET call... -->
<!-- here is an example logout link:
<a href="#
{request.contextPath}
/j_spring_security_logout">Logout</a> -->
<logout logout-url="/j_spring_security_logout"
logout-success-url="/general/logins/formLogin.html"
invalidate-session="true"/>
</http>
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/general/logins/formLogin.html" />
</beans:bean>
<!-- test with this before you hook up your LDAP or other Authentication Manager -->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="joe.blow@icesoft.com" password="pass1234" authorities="ROLE_READER"/>
<user name="ben.simpson@icesoft.com" password="pass5678" authorities="ROLE_READER"/>
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
<beans:property name="invalidSessionUrl" value="/general/logins/sessionExpired.html" />
<!-- this permits redirection to session timeout page from javascript/ajax or http -->
<beans:property name="redirectStrategy" ref="jsfRedirectStrategy" />
</beans:bean>
<beans:bean id="jsfRedirectStrategy" class="com.icesoft.spring.security.JsfRedirectStrategy"/>
<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
</beans:beans>
The tutorial used to work by redirecting to main.jsf as the welcome page from index.html. Then, without the additional line in step two above, the application would rerequest main.jsf when the user logged in and then the user would be able to see the additional links available to them.
Now an additional target is required to get the user redirected to a .jsf page after successful login (which is what the new line does) otherwise the application continually redirects to welcome.html.
The following test was performed against Spring Security sample application to check validity of this JIRA:
1. Added ICEpush dependancy to the pom.xml of sample application
<dependency>
<groupId>org.icepush</groupId>
<artifactId>icepush</artifactId>
<version>3.0.1</version>
</dependency>
2. Added 2 parameters to web.xml:
<context-param>
<param-name>org.icefaces.lazyPush</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.icefaces.strictSessionTimeout</param-name>
<param-value>true</param-value>
</context-param>
3. Set session expiry to 1 minute.
4. Loaded application and logged in as one of the users.
After a minute of inactivity session expiry popup window with reset button appeared automatically without any interaction on my side. Click on reload button in a popup redirected me to the session expiry page as I was expecting.
Screenshots attached.