Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: custom login messages when session expires

  1. #1
    Join Date
    Sep 2005
    Location
    Newcastle, Australia
    Posts
    61

    Question custom login messages when session expires

    Hi all

    When acegi redirects a user to the login page upon httpsession expiry, i'd like to display a 'session expired' message, so they know why they are now at the login page

    is there a point somewhere where i can trap the 'session has expired' event and maybe set a request attribute or request http param immediately before the user is directed to the login page?

    i'm guessing this is a fairly common requirement. what are the general best practices for implementing "your session has expired. please login again" functionality?

    thanks

  2. #2
    Join Date
    Sep 2005
    Location
    Newcastle, Australia
    Posts
    61

    Default

    If someone can point me in the right direction that would be great.

    Essentially, I'm trying to determine the difference between
    1. when the user tries to access a secured resource and hasnt logged in
    2. when the user tries to access a secured resource and their http session has expired

    If (2) occurs above, I'd like to be able to tell the login page to display a 'your session has expired' message.

  3. #3
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    Sessions are maintained by the container and once one is destroyed, there is no way to determine the difference between a request from a user starting a new session and one from an existing user using a timed out session.

    You could set a session cookie and detect that when the user is forced to log in again. Using a synchronizer token (or some similar request parameter) would also give you the same behaviour.

  4. #4
    Join Date
    Oct 2005
    Location
    Arlington, VA
    Posts
    14

    Default

    I wrote a custom servlet filter that queries the HTTP request to see if it passed a session id and if that session id is valid. If it's not, I redirect to the login screen, passing a parameter that my JSP can detect to display a "session timed out" message.

    Here's the code for the filter:

    Code:
    import org.springframework.beans.factory.InitializingBean;
    
    import org.springframework.util.Assert;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    
    public class SessionExpirationFilter implements Filter, InitializingBean {
        //~ Instance fields ================================================================================================
    
        private String expiredUrl;
    
        //~ Methods ========================================================================================================
    
        public void afterPropertiesSet() throws Exception {
            Assert.hasText(expiredUrl, "ExpiredUrl required");
        }
    
        /**
         * Does nothing. We use IoC container lifecycle services instead.
         */
        public void destroy() {}
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
            Assert.isInstanceOf(HttpServletRequest.class, request, "Can only process HttpServletRequest");
            Assert.isInstanceOf(HttpServletResponse.class, response, "Can only process HttpServletResponse");
    
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            
            HttpSession session = httpRequest.getSession(false);
    
            if (session == null &&
                httpRequest.getRequestedSessionId() != null &&
                !httpRequest.isRequestedSessionIdValid())
            {    
                String targetUrl = httpRequest.getContextPath() + expiredUrl;
                httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
                return;
            }
    
            chain.doFilter(request, response);
        }
    
        /**
         * Does nothing. We use IoC container lifecycle services instead.
         *
         * @param arg0 ignored
         *
         * @throws ServletException ignored
         */
        public void init(FilterConfig arg0) throws ServletException {}
    
        public void setExpiredUrl(String expiredUrl) {
            this.expiredUrl = expiredUrl;
        }
    }
    Then I make sure that the SessionExpirationFilter is the first filter applied to protected resources. Note that the login page (the page that a session expiration will redirect to) is NOT protected by SessionExpirationFilter (otherwise you end up with an infinite redirect loop).

    Code:
    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /login.spring*=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
    /**=sessionExpirationFilter,httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
            </value>
        </property>
    </bean>
    
    ...
    
    <bean id="sessionExpirationFilter" class="SessionExpirationFilter">
        <property name="expiredUrl" value="/login.spring?login_error=2"/>
    </bean>
    
    ...
    Then in my login page, I just check for the error parameter that I configured.

    Code:
    <c:if test="${param.login_error == 2}">
    	<br>
    	<h2 class="red">Your session has timed out.</h2>
    </c:if>
    
    ...
    It's been working so far.

    ---
    Christopher Pierce
    Last edited by macob; Jun 3rd, 2008 at 11:15 AM. Reason: bug in configuration example, missing wildcard in URL

  5. #5
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    Looks pretty good. So everything you need is actually already there in the servlet API. In that case, we should perhaps look at adding support detecting expired sessions in HttpSessionContextIntegrationFilter sometime in the future.

  6. #6
    Join Date
    Sep 2005
    Location
    Newcastle, Australia
    Posts
    61

    Default

    I'm not sure if it would make any sense, but my first instinct would be to add a sessionTimeoutUrl property to AuthenticationProcessingFilter

  7. #7
    Join Date
    Sep 2004
    Posts
    346

    Default Is there JIRA on this new functionality?

    Is there JIRA on this new functionality?

  8. #8
    Join Date
    May 2006
    Location
    Florianópolis, Brazil
    Posts
    57

    Default

    I would be an outstanding functionality, indeed, dear Watson.

  9. #9
    Join Date
    May 2008
    Posts
    4

    Default

    Just wondering is this functionality on the roadmap for spring security?

  10. #10
    Join Date
    May 2006
    Location
    Florianópolis, Brazil
    Posts
    57

    Default Abandonment

    It seems, my fellow forum colleagues, that abandonment has fell upon us.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •