-3

ViewExpiredException not throw on ajax request if JSF page is protected by j_security_check提供了登录页面为 JSF 页面时的解决方案。但是如果登录页面是 JSP 页面呢?

我有一个jsp登录页面:

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/core/login.jsp</form-login-page>
        <form-error-page>/core/login.jsp</form-error-page>
    </form-login-config>
</login-config>

在我的 JSF 页面(facelet)中,如果我单击非 Ajax 按钮,我将被重定向到 login.jsp。如果我单击 Ajax 按钮,它将保留在同一个 JSF 页面上。但是,在这两种情况下,我添加到 JSP 登录页面的调试代码都将显示在控制台中。

===

我使用 facelet 而不是 jsp 重写了登录页面

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/facelets/login.jsf</form-login-page>
        <form-error-page>/facelets/login.jsf</form-error-page>
    </form-login-config>
</login-config>

我添加了一个 AjaxLoginListener:

public class AjaxLoginListener implements PhaseListener {

        @Override
        public PhaseId getPhaseId() {
    //        return PhaseId.ANY_PHASE;
            return PhaseId.RESTORE_VIEW;
        }

        @Override
        public void beforePhase(PhaseEvent event) {
            System.out.println("    **** AjaxLoginListener: Before Phase: " + event.getPhaseId());
            // NOOP.
        }

        @Override
        public void afterPhase(PhaseEvent event) {
            System.out.println("    **** AjaxLoginListener: After Phase: " + event.getPhaseId());
            FacesContext context = event.getFacesContext();
            HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
            String originalURL = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
            String loginURL = request.getContextPath() + "/facelets/login.jsf";
            System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                    + this.getClass().getName()+" AjaxLoginListener: After Phase: originalURL: " + originalURL + " Login URL: "+loginURL);
            System.out.println("    **** AjaxLoginListener: After Phase: request.getRequestURI() " +request.getRequestURI());

            System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                    + this.getClass().getName()+" AjaxLoginListener: After Phase: isAjaxRequest " +context.getPartialViewContext().isAjaxRequest());

            if (context.getPartialViewContext().isAjaxRequest()
                    && originalURL != null
                    && loginURL.equals(request.getRequestURI()))
            {
                System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                        + this.getClass().getName()+" AjaxLoginListener: After Phase: AjaxRequest " + event.getPhaseId());
                try {
                    context.getExternalContext().redirect(originalURL);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new FacesException(e);
                }
            }
        }
    }

一旦我使用 facelet 而不是 jsp,我就能够调用侦听器。但是,它永远不会进入登录页面,因为 originalURL (RequestDispatcher.FORWARD_REQUEST_URI) 对于 Ajax 请求始终为 NULL。做错了什么?

4

1 回答 1

0

简单的解决方案是添加一个检查用户是否登录,如果没有,则重定向到登录页面:

    @Override
    public void afterPhase(PhaseEvent event) {
        System.out.println("    **** AjaxLoginListener: After Phase: " + event.getPhaseId());
        FacesContext context = event.getFacesContext();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        HttpSession session = request.getSession();

//        String originalURL = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);

        String loginURL = request.getContextPath() + "/facelets/login.dti";
        System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                + this.getClass().getName()+" AjaxLoginListener: After Phase:  Login URL: "+loginURL);
        System.out.println("    **** AjaxLoginListener: After Phase: request.getRequestURI() " +request.getRequestURI());

        System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                + this.getClass().getName()+" AjaxLoginListener: After Phase: isAjaxRequest " +context.getPartialViewContext().isAjaxRequest());

        if (context.getPartialViewContext().isAjaxRequest()
                && session.getAttribute("user") == null
                && loginURL.equals(request.getRequestURI()))
        {
            System.out.println("    **** "+new java.sql.Timestamp(System.currentTimeMillis()) + " -- "
                    + this.getClass().getName()+" AjaxLoginListener: After Phase: AjaxRequest " + event.getPhaseId());
            try {
                context.getExternalContext().redirect(loginURL);
            } catch (IOException e) {
                e.printStackTrace();
                throw new FacesException(e);
            }
        }

    }

但是,这里的显着缺点是登录后它不会转到原始页面。

于 2012-12-20T18:08:38.410 回答