16

私の Web アプリでは、ユーザーがログインすると、その ID をサーブレットの有効な ID のベクトルに追加し、ログアウトするとその ID をベクトルから削除して、現在アクティブなユーザーの数を確認します。ユーザーがログアウトするのを忘れました。

<meta http-equiv="Refresh" content="30; url=My_Servlet?User_Action=logout&User_Id=1111">

タグで彼を自動的にログアウトさせます。

しかし、多くのユーザーがログアウトせずにずっとそこにいることに気付きました。ブラウザーを閉じても、手動または自動でログアウトしない理由がわかりました。そのため、ユーザー ID が有効なユーザー ID ベクトルから削除されることはありません。

だから、私の質問は、ブラウザを閉じているユーザーをどのように検出して、サーブレットがベクターから ID を削除できるようにするかです。


トンネルの終わりに光が見えますが、まだ問題があります。私のプログラムには次のようなものがあります。

アクティブ ユーザー リスト:

User_1 : Machine_1 [ IP_1 address ]
User_2 : Machine_2 [ IP_2 address ]
User_3 : Machine_3 [ IP_3 address ]
...

セッション リスナーから、どのユーザーのセッションが終了したかを知るにはどうすればよいですか。したがって、そのユーザーをリストから削除するにはどうすればよいですか?

セッションが終了したときに HttpServlet のdestroy()メソッドが呼び出され、そこにあるユーザー ID を削除できることを期待していましたが、ユーザーがブラウザーを閉じたときに呼び出されないのはなぜですか? また、セッションが閉じたときに呼び出される HttpServlet に他のメソッドはありますか?

4

6 に答える 6

14

ブラウザーが閉じたことをサーバー側で知る方法はありません (JavaScript を使用してサーバーにメッセージを送信する場合を除きます)。どうしてあり得ますか?HTTP がどのように機能するかを考えてみてください。すべてが要求と応答です。

ただし、アプリケーション サーバーは、セッションがアクティブなときを追跡し、セッションが破棄されたとき (タイムアウトなど) も通知します。このページを見HttpSessionListenerて、これらのイベントを受信するように構成する方法を確認してください。その後、アクティブなセッションの数を簡単に追跡できます。

セッションがタイムアウトになる前に一定の (構成可能な) 時間が経過する必要があるため、アクティブなセッションの数は、現在のユーザーの実際の数よりも遅れます。ただし、これはある程度近いはずです (セッションタイムアウトを下げて精度を上げることができます)。1) セッションを自分で追跡するか、2) ブラウザーが閉じているときに非同期 JavaScript をサーバーに送信するよりも、はるかにクリーンで簡単です (送信を保証するものではありません)。

于 2008-11-18T18:47:58.500 に答える
7

サーブレット エンジンがセッションを破棄するときに ID を削除することをお勧めします。が呼び出されたHttpSessionListenerときにユーザーの ID を削除する を登録します。sessionDestroyed()

Diodeusのアイデアは、セッションがより迅速に終了したことを検出するのに役立ちます。

于 2008-11-18T18:37:05.107 に答える
3

JavaScript ではonbeforeclose、ユーザーがブラウザーを閉じたときに、イベントを使用してサーバーにコールバックを渡すことができます。

私は通常、これを行うために同期 Ajax 呼び出しを使用します。

于 2008-11-18T18:36:30.643 に答える
2

私は最近それをしなければなりませんでした、そしていくつかの検索の後、ネット上でいくつかの解決策を見つけました...それらはすべて普遍的に機能していません!

このタスクには onbeforeclose および onclose イベントが使用されます。ただし、問題が 2 つあります。ユーザーがページをリロードしたとき、または現在のページを変更したときに発生します。イベントが実際にウィンドウ/ページ/タブを閉じることであるかどうかを確認するためのトリックがあります (イベントを閉じると混乱するいくつかの Dom プロパティを調べます)。

  • それらはブラウザに依存します
  • トリックは文書化されていないため、脆弱です
  • そして実際には、ブラウザのバージョン/アップデートによって異なります...

そして最悪なことに、これらのイベントは最近のほとんどのブラウザーで無視されています。これは、ブラウザーを閉じたときにウィンドウから不正な広告が飛び出すことによって悪用されてきたためです。Safari、Opera、IE7 などでは起動されません。

指摘したように、ログインを使用するほとんどの Web アプリケーションは、しばらくするとユーザー セッションを破棄します。30分。貴重なリソースであるライセンスをより速く解放するために、ブラウザーを閉じるときにログアウトするように求められました。ユーザーはよくログアウトを忘れるので...

私が提供した解決策は、Ajax リクエスト (ユーザー ID の送信) で定期的に (たとえば 1 分) サーバーに ping を実行することでした。サーバーがたとえば 3 分間 ping を受信しない場合、ユーザーは切断されます。

于 2008-11-18T21:15:47.220 に答える
2

あなたがやろうとしていることを確実に実行する方法はありませんが、sblundy と Diodeus の両方が、ほとんどの状況をカバーする計画を持っています。ブラウザで Javascript をオフにしたり、インターネット接続がダウンしたり、電源が切れたりした人に対して、あなたができることは何もありません。一定期間非アクティブになった後、セッションを選別する必要があります(これは、セッションの破壊をリッスンするというsblundyの提案が行うことだと思います)。

于 2008-11-18T18:47:32.527 に答える
-1

これは、「ブラウザーの終了を検出する」ことを達成するための汚い方法です。これは、このサイトのどこかのフォーラムで見つけました。もう一度見つけたら、リンクします。

http 応答にヘッダーを追加します。追加のリクエストが来ると、これらの追加のヘッダーが含まれます。これらのヘッダーを確認し、存在しない場合はセッションを強制終了して、新しいセッションが開始されるようにすることができます。これはブラウザが閉じられているかどうかを「通知」しませんが、追加したヘッダーが見つからないため、誰かがウィンドウを閉じて戻ってきようとしているかどうかを知ることができます。

 wrapper.setHeader("Cache-Control", "no-cache, no-store, must-     revalidate");
 wrapper.setHeader("Pragma", "no-cache");
 wrapper.setDateHeader("Expires", 0);

 Where wrapper is a response wrapper.

 if (wrapper.getHeaderNames().size() < the number of headers you are expecting)
 request.getSession().invalidate();

 Not perfect but it might help someone.
于 2013-04-11T20:08:35.160 に答える