-3

JSF ページが j_security_check によって保護されている場合、ViewExpiredException が ajax 要求でスローされないは、ログイン ページが 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 ログイン ページに追加したデバッグ コードはコンソールに表示されます。

===

jsp の代わりに facelet を使用してログイン ページを書き直しました。

<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);
                }
            }
        }
    }

jsp の代わりに facelet を使用すると、リスナーを呼び出すことができました。ただし、Ajax リクエストの場合、元の URL (RequestDispatcher.FORWARD_REQUEST_URI) は常に 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 に答える