20

RichfacesとFaceletsでJSF1.2を使用しています。

多くのセッションスコープのBeanといくつかのアプリケーションBeanを含むアプリケーションがあります。

ユーザーは、たとえばFirefoxでログインします。ID="A"でセッションが作成されます。次に、Chromeを開き、同じクレデンシャルで再度ログインします。ID="B"でセッションが作成されます。

セッション「B」が作成されたら、セッション「A」を破棄できるようにしたい。どうやってするか?

また。Firefoxのユーザーが何かをしたときに、「他の場所からログインしたためにログアウトしました」というポップアップまたは何らかの通知を表示できるようにしたいと思います。

作成および破棄されたセッションを追跡するsessionListenerがあります。重要なのは、HTTPSessionオブジェクトをアプリケーションスコープのBeanに保存し、ユーザーが2回ログインしたことを検出したときにそれを破棄できるということです。しかし、何かが私にそれが間違っていて、機能しないことを教えてくれます。

JSFはサーバー側のどこかでセッションを追跡しますか?識別子でそれらにアクセスする方法は?そうでない場合、ユーザーが2回ログインしたときに、ユーザーの最初のログインを開始するにはどうすればよいですか?

4

3 に答える 3

20

DBに依存しないアプローチは、に変数を持たせて(andと)を実装Userすることです。このようにして、予期しないクラッシュが発生した後もWebアプリが機能し、DB値が更新されない可能性があります(もちろん、Webアプリの起動時にDBをリセットするを作成することもできますが、それはますます多くの作業になります)。static Map<User, HttpSession>HttpSessionBindingListenerObject#equals()Object#hashCode()ServletContextListener

は次のようにUserなります。

public class User implements HttpSessionBindingListener {

    // All logins.
    private static Map<User, HttpSession> logins = new ConcurrentHashMap<>();

    // Normal properties.
    private Long id;
    private String username;
    // Etc.. Of course with public getters+setters.

    @Override
    public boolean equals(Object other) {
        return (other instanceof User) && (id != null) ? id.equals(((User) other).id) : (other == this);
    }

    @Override
    public int hashCode() {
        return (id != null) ? (this.getClass().hashCode() + id.hashCode()) : super.hashCode();
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = logins.remove(this);
        if (session != null) {
            session.invalidate();
        }
        logins.put(this, event.getSession());
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        logins.remove(this);
    }

}

次のようにログインするUserと:

User user = userDAO.find(username, password);
if (user != null) {
    sessionMap.put("user", user);
} else {
    // Show error.
}

次に、を呼び出します。これにより、以前にログインしたユーザーがマップvalueBound()から削除され、セッションが無効になります。logins

ログアウトするUserと、次のようになります。

sessionMap.remove("user");

または、セッションがタイムアウトにvalueUnbound()なると、が呼び出され、ユーザーがloginsマップから削除されます。

于 2010-03-03T16:25:57.833 に答える
4
  1. データベースに整数フィールドを作成しますuserLoggedInCount
  2. ログインが増えるたびに、そのフラグが立てられ、結果がセッションに保存されます。
  3. リクエストごとに、データベースの値とセッションの値を確認し、セッションの値がDBの値よりも小さい場合は、invalidate()セッションでデータベースの値をデクリメントします。
  4. セッションが破棄されるたびに、値もデクリメントされます。
于 2010-03-03T15:22:40.890 に答える
1

HttpSessionBindingListenerを使用したBalusCからの回答が好きです。

しかし、Enterprise JavaBeansTM仕様、バージョン2.0には次のように書かれています。

エンタープライズBeanは、読み取り/書き込み静的フィールドを使用してはなりません。読み取り専用の静的フィールドの使用が許可されています。したがって、エンタープライズBeanクラスのすべての静的フィールドをfinalとして宣言することをお勧めします。

したがって、静的フィールドを使用せずにテーブルアプリケーションをワイドに格納するApplicationScopedBeanを作成する方がよいのではないでしょうか。

それを試してみましたが、うまくいくようです...

これが私の例です:

@Named
@ApplicationScoped
public class UserSessionStorage implements java.io.Serializable,HttpSessionBindingListener {

@Inject
UserManagement userManagement;

private static final long serialVersionUID = 1L;

/**
 * Application wide storage of the logins
 */
private final Map<User, List<HttpSession>> logins = new HashMap<User, List<HttpSession>>();

@Override
public void valueBound(final HttpSessionBindingEvent event) {
    System.out.println("valueBound");

    /**
     * Get current user from userManagement...
     */
    User currentUser = userManagement.getCurrentUser();

    List<HttpSession> sessions = logins.get(currentUser);
    if (sessions != null) {
        for (HttpSession httpSession : sessions) {
            httpSession.setAttribute("invalid", "viewExpired");
        }
    } else {
        sessions = new ArrayList<HttpSession>();
    }
    HttpSession currentSession = event.getSession();
    sessions.add(currentSession);
    logins.put(currentUser, sessions);
}

@Override
public void valueUnbound(final HttpSessionBindingEvent event) {
    System.out.println("valueUnbound");

    User currentUser = userManagement.getCurrentUser();

    List<HttpSession> sessions = logins.get(currentUser);
    if (sessions != null) {
        sessions.remove(event.getSession());
    } else {
        sessions = new ArrayList<HttpSession>();
    }
    logins.put(currentUser, sessions);
}

}

->私の英語でごめんなさい...

于 2013-06-17T08:42:56.527 に答える