3

WebアプリケーションはJBoss7.1.1およびJava(JPA2およびRichFaces4)で実行されます。現時点での問題は、ユーザーがログインしているとアプリケーションがスタックするだけで、しばらくの間アプリケーション内で何もしないことです(おそらくセッションのタイムアウトが原因です)。次に、ユーザーはWebアプリケーションを再度ロードする必要がありますが、これはあまり専門的ではありません。

上記のテクノロジーを使用して自動ログアウトを実装する方法について、ヒントを教えてください。

[更新]
私は多くの可能性を試しましたが、どれも正しく機能しません。私の考えは、セッションがいつ期限切れになるかを知っているSessionTimeoutListenerを実装することです。

@Logged
@WebListener
@Named
public class SessionTimeoutListener implements HttpSessionListener
{
    @Inject
    private Logger logger;

    @Override
    public void sessionCreated(HttpSessionEvent event)
    {
        // not used.
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event)
    {
        logger.info("Session destroyed.");

        ApplicationContext.setAutoLoggedOut(true);
    }
}

これは機能します。しかし、その後、すべての問題が発生します。FacesContextがnullであるため、リダイレクトできません。NameNotFoundExceptionなどの例外が発生するため、プッシュイベントを発生させることができません(多くのことを試しましたが、イベントの発生はこれでも機能しないようです)。次に、ApplicationContext.isAutoLoggedOut()でa4j:pollを試しましたが、ポーリングイベントを実行するとセッションが期限切れにならないため、これも機能しません。私はいつも行き止まりになります。SessionTimeoutListenerからなんらかの方法でリダイレクトできれば、これが解決策になります。

[考えられる解決策]
セッションの有効期限が切れた後、ビュー内のいずれかのボタンをクリックすると実行されるログアウトに満足しました。この現在のソリューションは基本的なものであり、まだ本番環境には適用できませんが、このソリューションは機能し、それを基に構築します。上位のSessionTimeoutListenerを使用します。さらに、SessionTimeoutListenerの後に呼び出されるPhaseListenerを使用しているため、セッションが期限切れになると、SessionTimeoutListenerが呼び出されてセッションが破棄されますが、SessionTimeoutPhaseListenerにはまだFacesContextがあります。そこで、そこからログアウトページにリダイレクトできます。

public class SessionTimeoutPhaseListener implements PhaseListener
{
    private static final long serialVersionUID = -8603272654541248512L;

    @Override
    public void beforePhase(PhaseEvent event)
    {
        //not used.
    }

    @Override
    public void afterPhase(PhaseEvent event)
    {
        FacesContext facesContext = event.getFacesContext();

        if (ApplicationContext.isAutoLoggedOut())
        {
            ApplicationContext.setAutoLoggedOut(false);

            try
            {
                facesContext.getExternalContext().redirect("./logout.xhtml");
            }
            catch (IOException e)
            {
            }
        }
    }

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

ApplicationContextは、ブール変数を格納する@ApplicationScopedを持つクラスですが、現在アプリケーションを使用しているすべてのユーザーに影響するため、これを変更する必要があります。それを解決するために、いくつかの「スレッドローカルコンテキスト」について考えます。自動ログアウトと手動ログアウトを区別する必要があります。どちらの場合も、リスナーが呼び出されます。このソリューションは現時点では機能しますが、「autoLoggedOut」をfalseに設定しないと、JSFによって何度も呼び出されるため(ブラウザーでリダイレクトループエラーが発生します)、PhaseListenerでのリダイレクトも注意が必要です。 ..私が言ったように、基本的なことだけですが、PhaseListenerを使用することがおそらく唯一の適切な解決策です。

4

4 に答える 4

3

これを行うには2つの方法があります。

1プルメカニズムを使用する5秒ごとに、セッションが有効かどうかをサーバーに確認し続けます。サーバーが有効と言った場合は、指定された時間スリープし、サーバーが無効と言った場合は、ユーザーにメッセージを表示してログアウトします。

2プッシュメカニズムを使用するを使用a4j:pushします。サーバーではTimerTask、5秒ごとに実行され、セッションが有効かどうかを確認します。セッションが有効であるかどうかを確認し、無効である場合はスリープし、ユーザーにメッセージを送信してからログアウトします。

このリンクを確認してくださいが、RichFaces4オンラインデモが機能していないようです

RichFacesにPrimefacesIdleMonitorのようなものがあるかどうかはわかりません

別の解決策は、カスタムHttpSessionListenerを使用することです

于 2012-05-30T14:47:12.687 に答える
1

ViewExpiredExceptionを処理する場合は、次の設定をweb.xmlに追加できます。

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/login.jsf</location>
</error-page>

さらに良いことに、ユーザーがまだセッションで利用可能かどうかを確認するPhaseListenertioを使用してください。

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("User")

そうでない場合は、ログインページに移動します。

FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null, "login");
于 2012-05-30T14:48:09.673 に答える
1

web.xmlでセッションタイムアウトを構成する必要があります。値は分単位であり、1未満にすることはできません。

<session-config>
    <!-- The application will have 15 minutes for session timeout -->
    <session-timeout>15</session-timeout>
</session-config>

セッションの有効期限が切れているかどうかを確認するフィルターを追加する必要があります。

<filter>
    <filter-name>SessionTimeoutFilter</filter-name>
    <filter-class>edu.home.TimeoutFilter</filter-class>
</filter>

フィルタは次のようになります。

public class TimeoutFilter implements Filter {
    private String startPage = "index.xhtml";

    public void init(FilterConfig filterConfig) throws ServletException {}
    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filterChain) throws IOException, ServletException {
        if ((request instanceof HttpServletRequest) &&
            (response instanceof HttpServletResponse)) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            if (!isValidSession(httpServletRequest)) {
                String timeoutUrl = httpServletRequest.getContextPath() + "/"
                    + startPage;
                //redirects to the first page
                httpServletResponse.sendRedirect(timeoutUrl);
            }
            filterChain.doFilter(request, response);
        }
    }

    private boolean isValidSession(HttpServletRequest httpServletRequest) {
        return (httpServletRequest.getRequestedSessionId() != null) &&
               httpServletRequest.isRequestedSessionIdValid();
    }
}
于 2012-05-30T15:02:41.143 に答える
1

Webなので、JavaScriptを使用できます。

var timeout;
var timeoutTime = 294000;
$().ready(function() {
    $(".loading").bind("ajaxSend", function() {
        timeout = setTimeout("TimedOut()", timeoutTime);
    }
});

function TimedOut() {
    //here I do an async call to test if a user is timed out
    var isTimedOut = yourMethodToTest();

    if(isTimedOut) { //do whatever you need to do here;
        alert("session timed out");
    }
    else { //restart the checker
        timeout = setTimeout("TimedOut()",timeoutTime);
    }
}
于 2012-05-30T17:21:32.033 に答える