8

私のチャット アプリケーションには、ログアウト ボタンがあり、正常に動作します。

ブラウザウィンドウを閉じたときにもアプリケーションをログアウトする必要があります..どうすればこれを達成できますか...

前もって感謝します...

4

11 に答える 11

12

クライアント側でこれを行う正確な方法はありません。ページが終了したときに発生するイベントはありません。これは、サーバー上のセッション終了イベントで行う必要があります。

onbeforeunload または unload を使用することはできますが、競合状態によりそれが妨げられます。また、ブラウザのクラッシュ、インターネット接続の切断などでは起動しません。

于 2012-11-15T15:23:21.997 に答える
7

最近 angularJS アプリでこの問題に対処しました - 主な問題は、更新してもログアウトしたくないが、タブを閉じるとログアウトしたいということでした.. onbeforeunload/onunload を使用した Ajax リクエストはありません応答を待つことが保証されているので、ここに私の解決策があります:

ログイン時にsessionStorage Cookieを設定しましたが、これはブール値です-ログイン応答を取得するとtrueに設定されます

sessionStorage.setItem('activeSession', 'true');

明らかに、ログアウト時に、このフラグを false に設定します

コントローラーが初期化されるか、window.onload (私の app.js ファイル内) を使用するとき - 私はこの activeSession bool をチェックします.. false の場合、この小さな if ステートメントがあります - 条件が満たされた場合、代わりにログアウトメソッドONLOADを呼び出しますonunload の

   var activeSession = sessionStorage.activeSession;
    if (sessionStorage.loggedOutOnAuth) {
        console.log('Logged out due to expiry already')
    }
    else if (!activeSession) {
        sessionStorage.loggedOutOnAuth = true;
        _logout()
    }

基本的に、「loggedOutAuth」ブールは、sessionStorage に activeSession がないためにページの読み込み時に期限切れになったことを知らせてくれるので、ループに陥ることはありません。

ハートビート/ウェブソケットを実装したくなかったので、これは私にとって素晴らしい解決策でした

于 2016-07-19T18:54:42.183 に答える
6

ログアウト コードをonunloadイベントに追加します。

window.onunload = function () {
    //logout code here...
}

JQuery では、 .unload()関数を使用できます。あまり時間がないので、Ajax リクエストを送信しても、結果がクライアントに届かない可能性があることに注意してください。

別のトリックは、小さな新しいウィンドウを開いて、そこでログアウトを処理することです。

window.open("logout url","log out","height=10,width=10,location=no,menubar=no,status=no,titlebar=no,toolbar=no",true);

ウィンドウを閉じることを無効にする (または少なくともユーザーに警告する) 場合は、次のコードを使用できます。

window.onbeforeunload = function(event) {
    //if you return anything but null, it will warn the user.
    //optionally you can return a string which most browsers show to the user as the warning message.
    return true;
}

もう 1 つのトリックは、数秒ごとにクライアントに ping を送信し続けることです。返信がない場合は、ユーザーがウィンドウを閉じたか、ブラウザがクラッシュしたか、チャット セッションを終了させるネットワークの問題が発生したと考えられます。クライアント側では、この ping パッケージを受信しない場合、ネットワーク接続またはサーバーに問題があると想定して、ログアウトの警告を表示できます (オプションで、ユーザーを再度ログインさせることもできます)。

于 2012-11-15T15:22:45.727 に答える
1

もう 1 つのアプローチは、ある種の「キープアライブ」です。ブラウザ ページは、約 1 分ごとに小さな ajax リクエストでサーバーに「ping」します。サーバーが通常の ping を取得しない場合、セッションは閉じられ、使用できなくなります。

最適化として、その間にサーバーに別のリクエストを行った場合、ping をスキップできます。

利点:

  • 複数のウィンドウを開いたままでも動作します
  • F5 /リフレッシュで問題なし
  • サーバーにいくつかの使用統計を提供できます

短所:

  • ウィンドウが閉じられると、ユーザーがログアウトされるまでに遅延が発生します
  • 少しネットワーク帯域幅を使用します
  • サーバーの追加負荷
  • ユーザーは、ページが常に「家に電話をかけている」ことに懸念を抱いている可能性があります。
  • 実装がより困難

私は実際に Web アプリでこれを行ったことはありません。代替手段としてそこに置くだけです。サーバーがあなたがまだそこにいるかどうかを知る必要があるチャットアプリに適したオプションのようです.

ポーリング/ping ではなく、ページが開いている間、「長時間実行される要求」を開いたままにする別の可能性があります。チャット アプリは、新しいメッセージと通知を受信するために、このようなソケットを必要とします。ページが閉じられると、ソケットも閉じられ、サーバーは閉じられたことを認識できます。次に、クライアントが新しいソケットを確立するのを少し待ちます。確立されない場合は、ページが閉じていると見なしてセッションを削除します。これには、サーバー上に少し特殊なソフトウェアが必要になります。

于 2015-12-09T15:38:18.037 に答える
1

一部の Web サイトでは、次のスクリプトを使用して、ウィンドウが閉じているかどうかを検出しています。

if(window.screenTop > 10000)
alert("Window is closed");
else
alert("Window stillOpen");

代わりに正しいアクションを追加する必要がありますalert()

こちらもご覧ください-これは、ウィンドウが閉じていることを検出するために必要なものだと思います

于 2012-11-15T15:22:59.513 に答える
1

私は解決策を手に入れました、

window.onunload = function () {
    //logout code here...
}

私を支えてくれたすべての人に感謝します...

于 2012-11-16T08:37:48.707 に答える
0

私はここでこの問題を抱えていましたが、別の解決策があります:

    checkSessionTime();
    $interval(checkSessionTime, 2000);
    function checkSessionTime() {
        var now = (new Date()).getTime();
        if (!$localStorage.lastPing) {
            $localStorage.lastPing = now;
        }

        if ($localStorage.lastPing < now - 5000) {
            $localStorage.lastPing = undefined;
            AuthService.logout();
        } else {
            $localStorage.lastPing = now;
        }
    }

サーバーへのpingのオーバーヘッドを追加したり、ウィンドウのアンロードイベントに依存したりしないため、このソリューションが気に入っています。このコードは$app.run.

私はJWT認証でangularを使用しています。この方法でログアウトすることは、認証トークンを取り除くことを意味します。ただし、サーバー側でセッションを終了する必要がある場合は、セッションを維持するために ping を実行し続ける代わりに、セッションの終了時に 1 つの ping を実行するように Auth サービスを構築できます。

この解決策は私のケースを解決します。私の意図は、不要なユーザーがタブを閉じて PC から離れたときに誰かのアカウントにアクセスできないようにすることです。

于 2016-08-27T03:26:42.260 に答える
0

多くの検索の後、私は以下のカスタマイズされたコードを JavaScript で書き、C# でセッションを強制終了するためのサーバー側コードを書きました。

以下のコードは、同じ Web サイトが複数のタブで開かれている場合に拡張されるため、Web サイトの 1 つのタブが開くまでセッションは有効です。

//Define global varible 
var isCloseWindow = false;

 //Jquery page load function to register the events

 $(function () {
        //function for onbeforeuload
        window.onbeforeunload = ConfirmLeave;
        //function for onload
        window.onload = ConfirmEnter;

        //mouseover for div which spans the whole browser client area 
        $("div").on('mouseover', (function () {
        //for postback from the page make isCloseWindow global varible to false
            isCloseWindow = false;
        }));
        //mouseout event
        $("div").on('mouseout', (function () {
     //for event raised from tabclose,browserclose etc. the page make isCloseWindow global varible to false
            isCloseWindow = true;
        }));
    });
     //Key board events to track  the  browser tab or browser closed by ctrl+w or alt+f4 key combination
    $(document).keydown(function (e) {
        if (e.key.toUpperCase() == "CONTROL") {
            debugger;
            isCloseWindow = true;
        }
        else if (e.key.toUpperCase() == "ALT") {
            debugger;
            isCloseWindow = true;
        }
        else {
            debugger;
            isCloseWindow = false;
        }
    });

    function ConfirmEnter(event) {
        if (localStorage.getItem("IsPostBack") == null || localStorage.getItem("IsPostBack") == "N") {
            if (localStorage.getItem("tabCounter") == null || Number(localStorage.getItem("tabCounter")) == 0) {
                //cookie is not present
                localStorage.setItem('tabCounter', 1);

            } else {
                localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) + 1);
            }
        }
        localStorage.setItem("IsPostBack", "N");
    }
    function ConfirmLeave(event) {
        if (event.target.activeElement.innerText == "LOGOUT") {
            localStorage.setItem('tabCounter', 0);
            localStorage.setItem("IsPostBack", "N");
        } else {
            localStorage.setItem("IsPostBack", "Y");
        }
        if ((Number(localStorage.getItem('tabCounter')) == 1 && isCloseWindow == true)) {
            localStorage.setItem('tabCounter', 0);
            localStorage.setItem("IsPostBack", "N");
            **Call Web Method Kill_Session using jquery ajax call**
        } else if (Number(localStorage.getItem('tabCounter')) > 1 && isCloseWindow == true) {
            localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) - 1);
        }
    }

 //C# server side WebMethod
 [WebMethod]
  public static void Kill_Session()
    {
        HttpContext.Current.Session.Abandon();
    }
于 2016-12-16T05:27:48.543 に答える
0
tabOrBrowserStillAliveInterval;

constructor() {
  // system should logout if the browser or last opened tab was closed (in 15sec after closing)
  if (this.wasBrowserOrTabClosedAfterSignin()) {
    this.logOut();
  }

  // every 15sec update browserOrTabActiveTimestamp property with new timestamp
  this.setBrowserOrTabActiveTimestamp(new Date());
  this.tabOrBrowserStillAliveInterval = setInterval(() => {
    this.setBrowserOrTabActiveTimestamp(new Date());
  }, 15000);
}

signin() {
  // ...
  this.setBrowserOrTabActiveTimestamp(new Date());
}

setBrowserOrTabActiveTimestamp(timeStamp: Date) {
  localStorage.setItem(
    'browserOrTabActiveSessionTimestamp',
    `${timeStamp.getTime()}`
  );
}

wasBrowserOrTabClosedAfterSignin(): boolean {
  const value = localStorage.getItem('browserOrTabActiveSessionTimestamp');

  const lastTrackedTimeStampWhenAppWasAlive = value
    ? new Date(Number(value))
    : null;
  const currentTimestamp = new Date();
  const differenceInSec = moment(currentTimestamp).diff(
    moment(lastTrackedTimeStampWhenAppWasAlive),
    'seconds'
  );

  // if difference between current timestamp and last tracked timestamp when app was alive
  // is more than 15sec (if user close browser or all opened *your app* tabs more than 15sec ago)
  return !!lastTrackedTimeStampWhenAppWasAlive && differenceInSec > 15;
}

仕組み: ユーザーがブラウザーを閉じるか、開いているすべてのアプリタブを閉じると、15 秒のタイムアウト後にログアウトがトリガーされます。

  • 複数のウィンドウを開いた状態で動作します
  • サーバーに追加の負荷がかからない
  • F5 /リフレッシュで問題なし

ブラウザの制限が、ログアウト前に 15 秒のタイムアウトが必要な理由です。ブラウザは、ブラウザを閉じる、タブを閉じる、タブを更新するなどのケースを区別できないためです。これらのアクションはすべて、ブラウザーによって同じアクションと見なされます。したがって、15 秒のタイムアウトは、ブラウザーの終了または開いているすべてのアプリタブの終了 (および更新/F5 のスキップ) のみをキャッチするための回避策のようなものです。

于 2021-02-22T10:56:35.563 に答える