2011-10-17 74 views
1

问题:我在我的应用程序的某个页面上走了一段时间。回过头来,点击一个链接,我得到一个“无法恢复视图ID”的消息。与刷新相同。正确处理会话超时的方法是什么?

我就可以开始一个新的会话,但我必须手动编辑网址如下:

活动地址窗口:

http://localhost:8080/myapp/index.xhtml?windowId=e9d 

http://localhost:8080/myapp/index.xhtml 

然后一个新的会话已建立,用户必须再次登录,这是我想要的。

在研究如何处理这个问题时,我看到很多“解决方案”基本上使会话保持活跃状态​​,通过使用客户端JavaScript定期发送请求以保持会话的活跃。我个人认为这不是一个理想的解决方案。

我想要的是,当会话超时时,对任何非公共页面的所有后续请求都需要定向到index.xhtml。对不需要登录的页面的引用应该使用新的会话对象。最好这将只使用JSF 2定义的设施来处理,但我不介意写一个Servlet过滤器,如果这是需要的。

任何人都可以提供一个链接,我怎么错过了?

回答

4

是不是在Filter,是的。你可以使用HttpServletRequest#getRequestedSessionId()检查,如果客户端发送一个会话cookie和HttpServletRequest#isRequestedSessionIdValid()来检查它是否仍然有效(即会话未在服务器端已经过期):

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { 
    HttpServletRequest req = (HttpServletRequest) request; 
    HttpServletRequest res = (HttpServletResponse) response; 

    if (req.getRequestedSessionId() != null && !req.isRequestedSessionIdValid()) { 
     res.sendRedirect(req.getContextPath() + "/index.xhtml"); 
    } else { 
     chain.doFilter(request, response); 
    } 
} 

但是,这带来了另一个问题,你如何过滤登录用户?如果会话过期,则用户不再登录,对吧?如果用户已登录,您也可以仅检查过滤器。

+0

我正在处理应用程序级别的用户认证。有一个叫做Login的@SessionScoped bean,它的一个属性是User对象,如果用户没有登录,它是null。我想我知道如何从过滤器中获取托管bean,所以我可以修改你的示例代码因此。我可以假设sendRedirect()调用将中止进一步的请求处理吗? – AlanObject

+0

是的,它会。所有其他过滤器/ servlet(也是'FacesServlet')只有在您通过'chain.doFilter()'继续请求/响应时才会被调用。相关:http://stackoverflow.com/questions/6883430/prevent-accessing-restricted-page-without-login-in-jsf2 – BalusC

+0

我遇到了这个解决方案的一些麻烦,因为我需要访问我的会话范围对象来确定认证状态。在过滤器中访问FacesContext对象是最好的。是否可以/更好地使用PhaseListener来做到这一点?我正在查看您的网页:http://balusc.blogspot.com/2006/06/communication-in-jsf.html#AccessingTheFacesContextInsideHttpServletOrFilter – AlanObject

相关问题