Redirecting after HttpSession time out

2020-02-25 23:15发布

I have been looking at many posts on this topic but couldn't get a solution that works in my case.

I am using Java EE 6 with JSF 2.0 (deployed on JBoss AS 7.1)

In my web.xml I have:

    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

and I want the user to be redirected to the login page when the session automatically times out.

what I have tried:

Approach 1: using filter

I have tried the following filter:

@WebFilter()
public class TimeOutFilter implements Filter {

        @Override
        public void init(FilterConfig filterConfig) throws ServletException { 
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
        ServletException {
        System.out.println("filter called");
        final HttpServletRequest req = (HttpServletRequest) request;
        final HttpSession session = req.getSession(false);
        if (session != null && !session.isNew()) {
            chain.doFilter(request, response);
        } else {
            System.out.println("Has timed out");
            req.getRequestDispatcher("/logon.xthml").forward(request, response);
        }
    }

    @Override
    public void destroy() {
    }
}

In the web.xml I have tried

<filter-mapping>
    <filter-name>TimeOutFilter</filter-name>
    <url-pattern>*.xhtml</url-pattern>
</filter-mapping>

and

<filter-mapping>
    <filter-name>TimeOutFilter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

The filter works as it is called on every request (logging of "fiter called" in the console). However it is not called when the session times out.

Approach 2: HttpSessionLister

I have tried to use a HttpSessionListerner. The method called having the following signature:

public void sessionDestroyed(HttpSessionEvent se) {
}

I wasn't able to redirect to a specific page. When I want to redirect a user I usually use the NavigationHandler from the FacesContext but in this case there is no FacesContext (FacesContext.getCurrentInstance() returns null).

According to this post, the HttpListener cannot redirect the user because it is not part of a request.

Question

What is the best way to go to solve this problem? What can I do to make one of the two above-mentioned approaches to work?

4条回答
趁早两清
2楼-- · 2020-02-25 23:21

You could use a Filter and do the following test:

HttpSession session = request.getSession(false);
if(session != null && !session.isNew()) {
    chain.doFilter(request, response);
}
 else {enter code here
    response.sendRedirect("/login.jsp");
 }
查看更多
不美不萌又怎样
3楼-- · 2020-02-25 23:25

I understand that you are using java-EE6 and JSF,but if you could try using JSP code or convert this code below to work in a servlet. Assuming you are using the username to check for session,after setting the session-timeout in the web.xml file.Please note that JSP code and servlet code are similar. Your code for validating of session could look like this.(JSP Format) If the username serves as the primary key in your database.

 <%
    String un = (String)session.getAttribute("un");

    if(un == null){
   response.sendRedirect(login page);
   return;
}else{
      code to process login form
}
    %>

Servlet code could look like this

String un = (String)session.getAttribute("un");
if(un == null){
   response.sendRedirect(loginPage);
}
查看更多
时光不老,我们不散
4楼-- · 2020-02-25 23:28

In HttpSessionListerner you cannot send any response to User. One good way to achieve this is with polling, the browser sends HTTP requests at regular intervals and immediately receives a response.
There are many ways to do that:

  1. You can use plain old javascript to poll: This will work in cross browser environment.

    function refresh() {

    // make Ajax call here, inside the callback call:
    
    setTimeout(refresh, 5000);
    
    // ...
    

    }

    // initial call, or just call refresh directly
    

    setTimeout(refresh, 5000);

  2. You can use Web Sockets. Web socket specification is present on below link:

    http://dev.w3.org/html5/websockets/

查看更多
做个烂人
5楼-- · 2020-02-25 23:37

You can't send a HTTP response as long as the client hasn't send a HTTP request. Simple as that. That's just how HTTP works. The Internet would otherwise have looked very different if any website was able to unaskingly push a HTTP response without the client having requested for it.

A JavaScript based heartbeat based on client's keyboard/mouse activity like as answered here, or a meta refresh header like as answered here would be the solution if you've basically a single-page webapp (thus, you're effectively not using the session scope but the view scope), but that won't work nicely if you've the page open in multiple tabs/windows in the same session.

Websockets is in theory the right solution to push something to the client, but this requires in turn an active session. Chicken-Egg problem. Also, it wouldn't work in older browsers currently still relatively widely in use, so it should currently merely be used for progressive enhancement.

Your best bet is to just define an error page which deals with the case when the enduser invokes an action while the session is expired. See also javax.faces.application.ViewExpiredException: View could not be restored.

查看更多
登录 后发表回答