5

私のJSFアプリケーションにはFilter、authenticati0nプロセスをチェックするために使用されるがあります。認証が失敗すると、フィルターはにリダイレクトされlogin.xhtmlます。

FacesMessageからログインページにを渡すにはどうすればよいFilterですか?

以下で使用しましたが、OKではありません。

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

AuthenticationFilter.java

public class AuthenticationFilter implements Filter  {
    private FilterConfig config;
    private ServletContext servletContext;

    public void init(FilterConfig filterConfig) {
        config = filterConfig;
        servletContext = config.getServletContext();
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpSession session = httpRequest.getSession();
        User user = (User) session.getAttribute(Constants.LOGIN_USER);
        if (user == null) {
            ...
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
        } else if (!user.getRole().equals(Role.SYSTEM_ADMINISTRATOR)) {
            ....
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
        servletContext.log("Exiting the filter");
    }

    public void destroy() {
        //Nothing to do.
    }
}
4

2 に答える 2

10

FacesContextによって作成されますFacesServlet。フィルタ内にいるときは、まだ呼び出されていません。フィルタはサーブレットの前に実行されます。FacesContextそのため、フィルターに手を入れることはできません。さらに、facesメッセージはリクエストスコープであるため、リダイレクトによってメッセージはとにかく消えてしまいます。

login.xhtmlの間にそれ自体を設定しましょう<f:event type="preRenderView">。最も簡単な方法は、フィルターに一時的にセッションスコープに配置させることです。

session.setAttribute("message", message);
httpResponse.sendRedirect(loginView);

次に、次のプリレンダリングビューリスナーメソッドでセッションスコープから削除しますlogin.xhtml

String message = (String) externalContext.getSessionMap().remove("message");

if (message != null) {
    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));
}
于 2012-12-21T05:22:26.867 に答える
0

EJBタイマーでFacesContextを取得しようとすると、同様の問題が発生しました。BalusCは、これを行うことは不可能であると複数のスレッドで指摘しています。または、「ServletContextListener」を使用することもできますが、ScheduledExecutorServiceは、EJBタイマーほど適切にスケジューリングを定義しません。

いずれにせよ、彼の提案の1つは、マネージドBeanに裏打ちされたページングされたJSFに実際にWebリクエストを送信して、タイマーで設定したいアプリケーションスコープのBeanのメソッドを利用することでした。

これについては、希望するメッセージとユーザーのIPアドレスなどを使用してJSFページにパラメーターを渡すという同様のことができるように思われるためです。そのページは、IPをキーとしてマップにそれらを格納するアプリケーションスコープのBeanが注入されたリクエストスコープのBeanによって裏付けられる可能性があります。次に、ユーザーがログインページにリダイレクトされると、そのページは、同じアプリケーションスコープのBeanが注入されたリクエストスコープのBeanでgetエラーメッセージメソッドを呼び出し、そのIPまたはそれらの行に沿った何かのエラーメッセージを取得します。

いずれにせよ、BalusCの答えはこれよりも十分で適切であると確信していますが、彼の「ejbタイマーからの要求を行うだけ」の提案は、アプリケーションスコープのBeanでメソッド呼び出しをスケジュールするためにうまく機能しました。ここでその可能な使用法をアップします。

@BalusC私が言及している投稿について何か考えがありますか?見つかりません。

于 2012-12-22T06:33:38.307 に答える