Question

Hi I have been unable to solve the following problem in Wicket 6.*:

In our webapp we are using wicket-auth-roles to manage authentication/authorization. When session expires, user should be redirected to a page set by getApplicationSettings().setPageExpiredErrorPage(SomePage.class) on his next action. However, if the user tries to access a page which doesn't allow guests, he is redirected to a login page skipping the PageExpiredPage altogether.

My question is - how can I display "Session has expired." message to the user?

Among other things, I have tried session.info("message") during onInvalidate phase of session's lifecycle, however the feedback message is then rendered on the first page after login (not on the login page).

Thank you for your anwsers.

Was it helpful?

Solution 2

After bernie put me on the right path, I eventually figured out a solution to the problem:

First it is required to override RequestCycleListener:

public class SessionExpiredListener extends AbstractRequestCycleListener {
  public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
    if (handler instanceof IPageRequestHandler) {
        IPageRequestHandler pageHandler = (IPageRequestHandler) handler;

        HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();

        //check whether the requested session has expired
        boolean expired = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();

        //check whether the requested page can be instantiated with the current session
        boolean authorized = Session.get().getAuthorizationStrategy().isInstantiationAuthorized(pageHandler.getPageClass());

        if (expired && !authorized) {
            throw new PageExpiredException("Session has expired!");
        }

    }
    super.onRequestHandlerResolved(cycle, handler);
  }
}

Check for authorized prevents the session-expired message from displaying on log-out or when accessing unprotected pages.

Finally, you must register your listener and PageRequestHandlerTracker in your WebApplication:

getRequestCycleListeners().add(new SessionExpiredListener());
getRequestCycleListeners().add(new PageRequestHandlerTracker());

OTHER TIPS

You could use a RequestCycleListener to record when a PageExpiredException is thrown.

public class ExceptionMapperListener extends AbstractRequestCycleListener {

    @Override
    public IRequestHandler onException(RequestCycle cycle, Exception ex) {
        if (ex instanceof PageExpiredException) {
            // Record in session or request cycle
            // OR
            // Create a RenderPageRequestHandler yourself and add a page parameter
            // See DefaultExceptionMapper#internalMap(Exception)
        }
        return null;
    }
}

// In Application#init():
getRequestCycleListeners().add(new ExceptionMapperListener());

ORINAL ANSWER

(kept because it could still help...)

I haven't tried it myself since I don't use wicket-auth-roles, but try overriding the method AuthenticatedWebApplication#restartResponseAtSignInPage() with something like this:

if (isSessionExpired()) {
    PageParameters params = new PageParameters();
    params.add("showSessionExpired", true);
    throw new RestartResponseAtInterceptPageException(getSignInPageClass(), params);
} else {
    throw new RestartResponseAtInterceptPageException(getSignInPageClass());
}

And then in the SignInPageClass, display the desired message if the showSessionExpired page parameter is present.

I'm not sure how you implement isSessionExpired(), but you seem to have that part already covered.

OR

Depending on how you implemented isSessionExpired(), maybe you could do the following in your SignInPageClass:

if (sessionExpired()) {
    session.info("message")
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top