0

シナリオ:

ユーザーは、firefox を使用して website.com にログインします。ログイン資格情報は有効です。ユーザーはメンバーのページに誘導されます。

ユーザーは、chrome を使用して website.com にログインしようとします。ユーザーはすでに Firefox を使用してログインしているため、ログイン資格情報は有効です。システムはエラーをスローし、ユーザーに他のセッションを閉じて chrome 経由でログインするように求めます。

どうすればそれを検出できますか?現在、ユーザーが 1 つのブラウザーのみを使用している場合は検出できますが、ユーザーが 2 つの異なるブラウザーを使用して異なる時間にログインすると、問題が発生するようです。

EDIT* 言いたいのは、単に異なるブラウザーを使用するだけではなく、Web サイトでは複数のユーザーが同じログイン資格情報でログインできるようにするべきではありません。

4

4 に答える 4

3

アプリケーションはj2EE/servletベースであると想定しています。この場合、2つのブラウザーは互いに独立しているため、アプリケーションが干渉しない限り、2つのブラウザーは独自のsessionIdを持ち、独立して機能できます。

このシナリオを防ぐための実装方法の1つは、サーブレットにSessionIDとUserIDのハッシュマップを保持することです。これは、ログインが成功するたびに、たとえばフィルターやバルブを介して入力します。ハッシュマップにデータを入力するときは、他のセッションIDがすでにこのuserIDを使用していないかどうかを確認してください。使用する場合は、対応するsessionIDがまだアクティブかどうかを確認してください。アクティブでない場合は、ログインを許可し、古いセッションIDを削除します。アクティブな場合は、他のセッションを終了してログインを許可します。

于 2012-07-20T18:24:41.267 に答える
1

Spring Securityを使用している場合は、構成ファイルのパラメーターで指定できます。

プレーンJavaの場合-ログイン中にユーザーのセッションIDをストレージに配置します。彼が再度ログインしようとするときは、それを禁止する必要があります。ただし、ブラウザを閉じた後、ユーザーが非常に長い時間ストレージにいる状況を回避する必要があります(1つの可能な解決策は、短いセッションタイムアウト+キープアライブリクエストです)

于 2012-07-20T18:11:39.373 に答える
1

アプリケーションでは、アプリを呼び出すたびに更新されるユーザーのタイムアウトを維持します。タイムアウトが経過するか、ユーザーがログアウトを要求するまで、ユーザーをセッション (たとえば、Firefox セッション) に「ロック」するように定義できます。別のブラウザ (Chrome など) でログインすると、アクティブなセッションがあるかどうかがチェックされ、ある場合はログイン試行が拒否されます。

簡単な例を作ります。これは実稼働の準備が整っておらず、説明のみを目的としています。

class User {
    long lastCheckin;
    int userId;
    String username;
}

今、誰かがアプリでページを表示するなど、何かをするとき、あなたはこれをします

user.lastCheckin = System.currentTimeMillis();

今、誰かがログアウトを明確に要求した場合、あなたはこれを行います

user.lastCheckin = 0L;

今、誰かがログインしようとすると、あなたはこれをします

if(user.lastCheckin + PREDEFINED_TIMEOUT > System.currentTimeMillis()) {
    return new LoginResponse(false,"User is active in another session.");
}
于 2012-07-20T18:09:44.243 に答える
1

ServletContext などのアプリケーション スコープ変数に、ログインしているユーザーのマップを格納できます。たとえば、認証サーブレットでは、おそらく次のようなことができます。

Map<String,String> activeUsers = request.getSession().getServletContext().getAttribute("__ONLINE_AUTHENTICATED_USERS");
//if null, context hasn't been prepared yet, create and attach a new one?2

ただし、注意が必要です。アプリケーション スコープ変数であるため、ある程度のスレッド セーフを確保する必要があります。これは、servletContext.setAttribute/getAttribute が提供するものです (たとえば、これらの操作はスレッド セーフではありません)。これは、ある種のアプリケーション ライフサイクル リスナーを使用して servletContext を「初期化」し、ユーザー マップを持つことで処理できる場合があります。これにより、set/getAttribute について心配する必要がなくなります。マップ操作自体について考える必要があります (たとえば、jucConcurrentHashMap を使用しますか?)。

また、ユーザーがログアウトしたときやセッションがタイムアウトしたときのクリーンアップ (マップからの削除など) にも注意を払う必要があります。

また、このアプローチによってユーザーが長時間ロックアウトする可能性があることも考慮する必要があります (たとえば、ブラウザーを閉じても適切にログアウトしない、マッピングがクリアされる前にセッションがタイムアウトする必要がある)。

編集:スケーラビリティについても考える必要があり、これはアプリケーションによって異なります。100 万人のオンライン ユーザーを期待していますか? それとも数千だけ?

于 2012-07-20T18:36:37.903 に答える