2

Java EE 6 (JSF CDI EJB) を使用した Web アプリケーションで作業していますが、これは同時ログイン (同じユーザーとパス) を許可してはなりません。

私が好きなのは:

ユーザーが 2 回ログインした場合、最初のセッションを無効にする必要があり、古いセッション データ (SessionScope または Apache CODI の WindowScope などの他のスコープを持つすべての CDI Bean を含む) が新しいセッションに転送されます。

これは、指名手配のセッション ハイジャック アプローチのようなものです :-)

4

3 に答える 3

0

フィルターを使用してこの問題を解決しました

public class SessionReplicationFilter は Filter {

@Inject
SessionReplicationManager manager;

public SessionReplicationFilter() {
}


@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    //Process chain first 
    if (chain != null) {
        chain.doFilter(request, response);
    }

    //check http request
    if (request instanceof HttpServletRequest) {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        // Retrieve the session and the principal (authenticated user)
        // The principal name is actually the username
        HttpSession session = httpRequest.getSession();
        Principal principal = httpRequest.getUserPrincipal();
        if (principal != null && principal.getName() != null && session != null) {
            manager.checkExistingSession(principal.getName(), session)) 
        }
    }

}

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void destroy() {

}

}

マネージャーは次のように見えます

@ApplicationScoped public class SessionReplicationManager {

private Map<String, HttpSession> map = new ConcurrentHashMap<String, HttpSession>();


public boolean checkExistingSession(String user, HttpSession session) {
    if (map.keySet().contains(user)) {
        if (!session.getId().equals(map.get(user).getId())) {
            System.out.println("User already logged in ");
            HttpSession oldSession = map.get(user);
            // copies all attributes from the old session to the new session (replicate the session)
            Enumeration<String> enumeration = oldSession.getAttributeNames();
            while (enumeration.hasMoreElements()) {
                String name = enumeration.nextElement();
                System.out.println("Chaning attribut " + name);
                session.setAttribute(name, oldSession.getAttribute(name));
            }
            // invalidates the old user session (this keeps one session per user)
            oldSession.invalidate();
            map.put(user, session);
            return true;
        }
    } else {
        System.out.println("Putting "+user+" into session cache");
        map.put(user, session);
        return false;
    }
    return false;
}

}

CoDI ViewScope アノテーション付き Bean で非常にうまく機能します。

最初のユーザーが (AJAX) リクエストごとに無効になると、セッション期限切れの例外が発生します。これは、[セッションの復元] ボタンを使用しても簡単に処理できます。

viewscoped Bean の小さな問題は、新しいビュー ID を取得することだけです。それらを原点に戻すことで、すべてが正常に機能します。

追加する必要があるもの:

  • 自動ログアウト (ajax ポーリング、websockets など)
  • すべての viewscoped-id が保存されるある種のレジストリ

このコメントにはありません:

  • web.xml 構成

よろしく

于 2012-07-17T11:05:13.333 に答える
0

ユーザーにステートレス Bean を使用できるため、ログイン/再ログインを試行するたびに、現在のセッションが無効になります (ログイン手順の開始時)。

この種のアプローチを検討してください:

try {           
   session = request.getSession();   //the request is passed by another page or action
   if(session.getAttribute("user") != null) {

           //your code to forward or handle the existing user (re-log in/ do nothing etc.)
}
于 2012-07-17T08:42:53.700 に答える
0

Java EE 6 には、これに対する固有のメカニズムはありません。

進行中のユースケース (オープン チェックアウト プロセスなど) のようなものをあるセッションから別のセッションに転送したいとは思わないので、単純にユーザーの GUI 状態を追跡することをお勧めします。

RESTful URL は、これに対する理想的なアプローチのように思えます。最後のユーザー URL/ユーザー アクション (例: www.myapp.com/orders/new/12) を保持し、新しいログイン時に再度開きます。

これを DB に保持したくない場合は、アプリケーション スコープのマップ ユーザー ID / URL が KISS の方法かもしれません。

于 2012-07-17T06:43:58.873 に答える