9

JSF2を使用しています。私は次のようなカスタムの顔サーブレットを実装しました:

public class MyFacesServletWrapper extends MyFacesServlet {
    // ...
}

ここで、ユーザーがログインしていないときに、いくつかの認証チェックを実行し、リダイレクトを送信しています。

public void service(ServletRequest request, ServletResponse response) {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    if (...) {
        String loginURL = req.getContextPath() + "/LoginPage.faces";
        res.sendRedirect(loginURL);
    }
}

これは、ユーザーが別のページに移動しようとしたときに機能します。ただし、これは、JSFフォームがJSFコマンドリンク/ボタンによって送信された場合は機能しません。ラインsendRedirect()ラインがヒットして実行され、例外はスローされませんが、ユーザーは同じページに留まります。基本的に、視覚的な変化はまったくありません。

これがページナビゲーションでは機能するのに、フォーム送信では機能しないのはなぜですか?

4

2 に答える 2

19

具体的な問題は、JSF コマンドのリンク/ボタンが実際に ajax リクエストを送信し、それが特別な XML レスポンスを期待しているために発生する可能性が最も高いです。ajax リクエストへの応答としてリダイレクトを送信している場合、その URL に ajax リクエストを再送信するだけです。これは、リダイレクト URL が特別な XML 応答ではなく HTML ページ全体を返すため、フィードバックなしで失敗します。実際には、JSF ajax エンジンが現在の .xml を変更するように指示された特別な XML 応答を返す必要がありますwindow.location

しかし、実際にはもっと大きな問題があります。仕事に間違ったツールを使用することです。自家製のサーブレットではなく、すべての JSF 作業の責任者に取って代わるサーブレット フィルターを使用しないでください。FacesServlet

次のように、リクエスト/ビュー スコープの JSF バッキング Bean でログインを実行していると仮定します (コンテナー管理認証を使用している場合は、j_security_check を使用して Java EE / JSF でユーザー認証を実行する2 番目の例も参照してください)。

externalContext.getSessionMap().put("user", user);

次に、このフィルターのキックオフ例を実行する必要があります。

@WebFilter("/*") // Or @WebFilter(servletNames={"facesServlet"})
public class AuthorizationFilter implements Filter {

    private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<partial-response><redirect url=\"%s\"></redirect></partial-response>";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURL = request.getContextPath() + "/login.xhtml";

        boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
        boolean loginRequest = request.getRequestURI().equals(loginURL);
        boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
        boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));

        if (loggedIn || loginRequest || resourceRequest)) {
            if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
                response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
                response.setDateHeader("Expires", 0); // Proxies.
            }

            chain.doFilter(request, response); // So, just continue request.
        }
        else if (ajaxRequest) {
            response.setContentType("text/xml");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
        }
        else {
            response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
        }
    }

    // ...
}

以下も参照してください。

于 2013-01-29T11:39:07.683 に答える
0

FacesContext.getCurrentInstance()。getExternalContext()。redirect( "newpage.xhtml"); res.sendredirect(cpath)の代わりにこれを試してください。

于 2013-01-29T10:11:45.047 に答える