检查会话是否存在JSF

时间:2011-11-15 22:43:39

标签: session jsf jsf-2 viewexpiredexception

我有一个登录页面,我有一个User bean来验证一个人的用户名和密码。这个Bean是Session Scoped。 如果有人写了一个URL并尝试跳转登录页面,我该如何检查并将其重定向到登录页面?

另一方面。假设我已经登录并且我正在工作,突然我出去了一段时间,我的会话到期了。当我返回并尝试与表单进行交互时,它会发送一条消息,提醒我会话到期。发生这种情况时,如何再次重定向到登录表单?

提前致谢。希望我自己解释一下。

Mojarra 2.1.4,Tomcat 7,Tomahawk 1.1.11

2 个答案:

答案 0 :(得分:16)

  

如果有人写了一个URL并尝试跳转登录页面,我该如何检查并将其重定向到登录页面?

您似乎使用自行开发的身份验证。在这种情况下,您需要实现servlet filter。 JSF将会话范围的托管bean存储为HttpSession的属性,因此您可以在doFilter()方法中检查它:

HttpServletRequest req = (HttpServletRequest) request;
UserManager userManager = (UserManager) req.getSession().getAttribute("userManager");

if (userManager != null && userManager.isLoggedIn()) {
    chain.doFilter(request, response);
} else {
    HttpServletResponse res = (HttpServletResponse) response;
    res.sendRedirect(req.getContextPath() + "/login.xhtml");
}

将此过滤器映射到覆盖受保护页面的网址模式,例如/app/*


  

当我返回并尝试与表单进行交互时,它会发送一条消息,提醒我会话到期。发生这种情况时,如何再次重定向到登录表单?

据我所知,这涉及Ajax请求?对于普通请求,您可以在<error-page>中使用web.xml。如果在web.xml中将状态保存方法设置为客户端,如下所示

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

不是一个选项,那么您需要实现自定义ExceptionHandler

public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    public ViewExpiredExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void handle() throws FacesException {
        FacesContext facesContext = FacesContext.getCurrentInstance();

        for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents().iterator(); iter.hasNext();) {
            Throwable exception = iter.next().getContext().getException();

            if (exception instanceof ViewExpiredException) {
                facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, "viewexpired");
                facesContext.renderResponse();
                iter.remove();
            }
        }

        getWrapped().handle();
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

}

(请注意,此特定示例导航到viewexpired,因此它需要/viewexpired.xhtml作为错误页面

上述需要通过以下ExceptionHandlerFactory实施来解决:

public class ViewExpiredExceptionHandlerFactory extends ExceptionHandlerFactory {

    private ExceptionHandlerFactory parent;

    public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory parent) {
        this.parent = parent;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        return new ViewExpiredExceptionHandler(parent.getExceptionHandler());
    }

}

又需要在faces-config.xml中注册,如下所示:

<factory>
    <exception-handler-factory>com.example.ViewExpiredExceptionHandlerFactory</exception-handler-factory>
</factory>

答案 1 :(得分:1)

如果您要实现自己的系统,可以向用户添加一个名为 session 的属性或其他内容。此属性可以是 boolean ,因此每当会话启动时,您都可以将此属性设置为true。编写一个名为权限的方法,例如:

public void permission() throws IOException {

        if(userStatelessBean.getSession() == false) {
            System.out.println("*** The user has no permission to visit this page. *** ");
            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
            context.redirect("login.xhtml");
        } else {
            System.out.println("*** The session is still active. User is logged in. *** ");
        }
    }

在您想要限制的每个jsf页面(此示例)上,您可以在页面的最开头添加以下代码:

<f:metadata>
     <f:event type="preRenderView" listener="#{sesija.permission()}"/>
</f:metadata>

在呈现页面之前,将使用对象名称​​ sesija 调用JSF ManagedBean,并检查您在指定方法中创建的rulles是否满足。

我希望你觉得这很有用,

谢谢。