Как вы можете отобразить предупреждение о тайм-ауте сеанса, которое достаточно умно для обработки нескольких открытых браузеров или вкладок

Я реализовал предупреждение о тайм-ауте сеанса с помощью javascript, который просто спрашивает пользователя, хотят ли они продлить свой сеанс или выйти из системы. Проблема в том, что это для портала интрасети, где опытные пользователи часто имеют несколько окон или вкладок браузера, открытых одновременно для приложения. В настоящее время им будет предлагаться выйти из каждого окна браузера. Как я могу сделать код более умным, чтобы обнаруживать, что они активно используют другой сеанс браузера?


person Joel    schedule 12.12.2008    source источник
comment
Это интересный вопрос и очень практичный. Я буду ждать ответа на это, так как у меня нет немедленного ответа :)   -  person rajesh pillai    schedule 12.12.2008
comment
Понятия не имею, почему это было отклонено.   -  person MusiGenesis    schedule 12.12.2008
comment
Да, я тоже был удивлен. Я проголосовал за. Кроме того, поскольку Джоэл новичок в SO, он не сделал ничего плохого, чтобы отговорить его, проголосовав против :)   -  person rajesh pillai    schedule 12.12.2008
comment
Джоэл, я ищу решение, которое у тебя уже есть. Я хочу, чтобы все браузеры получали предупреждение и выходили из системы. Не могли бы вы поделиться своим кодом и методом о том, как вы это сделали?   -  person Tigran    schedule 17.10.2010
comment
предупреждение: я написал это еще в мои темные века программирования. dl.dropbox.com/u/203098/sessiontimeout.js   -  person Joel    schedule 20.10.2010
comment
Самое близкое, что я видел, чтобы справиться с этим, - это решение на основе JS, в котором учитывается только текущая вкладка, а предупреждение отображается после истечения времени ожидания сеанса, даже если сеанс был продолжен на других вкладках. Конечно, было бы неплохо иметь элегантное решение (с использованием файлов cookie или иным образом) для этого сценария, спустя почти четыре года после того, как вопрос был задан ...   -  person Amos M. Carpenter    schedule 04.09.2012
comment
@Joel, ваша ссылка мертва (и это понятно, поскольку с тех пор, как вы ее разместили, прошло более 7 лет). Не могли бы вы обновить ссылку? У меня аналогичное требование.   -  person Bmoe    schedule 13.04.2018


Ответы (4)


Вам нужно будет проверить состояние сеанса на сервере с помощью Ajax и отслеживать все открытые сеансы / окна, которые есть у пользователя. Тогда вы сможете настроить таргетинг только на один из доступных сеансов с предупреждением о выходе из системы.

В ответ на ваш комментарий:

Не используйте встроенный механизм сеанса, разработайте свой собственный, используя постоянный массив на стороне сервера или журнал базы данных.

Нет, в HTTP-запросе ничего не говорится о том, сколько браузеров открыто, но вы можете назначить свой собственный файл cookie с идентификатором сеанса, когда пользователь открывает каждое окно браузера. Сделайте вызов Ajax на сервер, посмотрите, не истек ли у пользователя тайм-аут, и если вы самая нижняя (или последняя) запись в журнале сеанса, то вы браузер, который получает предупреждение.

person Diodeus - James MacFarlane    schedule 12.12.2008
comment
2 мысли: 1) как проверить состояние сеанса приложения .NET без фактического расширения сеанса? 2) есть ли способ узнать, сколько окон браузера установлено у пользователя? Ничто в http-запросе не говорит вам об этом - person Joel; 12.12.2008
comment
Вызывайте функцию обновления сеанса, когда пользователь выполняет действие, не вызывайте эту функцию, когда вы проверяете статус сеанса. Вы можете определить, сколько браузеров открыто на основе строки агента, но не думайте, что вы можете обнаружить окна / вкладки каждого из них. - person Adam; 12.12.2008
comment
Я не понимаю, как это сработает. Кроме того, если они используют отдельные браузеры (например, IE и FF) или даже отдельные экземпляры одного и того же браузера, то у них разные сеансы, поэтому это не проблема. - person Joel; 12.12.2008

Вы не можете рассчитывать на то, что все вкладки / окна будут частью одного и того же сеанса, потому что они могут быть порождены и содержаться в отдельных процессах, и у вас нет особого контроля над этим.

Но если ваш код ссылается на файл cookie Javascript, вы можете проверить состояние псевдосессии с помощью обратной передачи (синхронного или асинхронного AJAX). Но тогда вы зависите от файлов cookie, включенных в браузере пользователя.

person Kon    schedule 12.12.2008

Это сработает?

Сохранить файл cookie Javascript и проверить его, чтобы определить, был ли сеанс расширен на другой вкладке?

похоже, это работает ...

person Joel    schedule 12.12.2008
comment
Спустя 4 года это все еще кажется правильным ответом, по крайней мере, для ASP.NET. Проблема в том, что вам нужна комбинация клиентского и серверного подходов, и я думаю, вы не можете получить его на стороне сервера (потому что вы можете отслеживать вход / выход или начало / конец сеанса, но не активность на стороне клиента. о чем сервер не знает). Я думаю, поэтому вам нужно именно то, что вы предлагаете здесь. Я выложу, когда заработаю. - person philw; 05.12.2012

Установить @ ng-idle @ ng-idle можно через NPM. Установите его, запустив:

npm install --save @ng-idle/core @ng-idle/keepalive angular2-moment

Настройте модуль вашего приложения. Откройте src / app / app.module.ts и импортируйте Ng2IdleModule, используя

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { NgIdleKeepaliveModule } from '@ng-idle/keepalive'; // this includes the core NgIdleModule but includes keepalive providers for easy wireup

import { MomentModule } from 'angular2-moment'; // optional, provides moment-style pipes for date formatting

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MomentModule,
    NgIdleKeepaliveModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

затем в component.ts

import { Component } from '@angular/core';

import {Idle, DEFAULT_INTERRUPTSOURCES} from '@ng-idle/core';
import {Keepalive} from '@ng-idle/keepalive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

    currentPath: String;

    idleState = 'Not started.';
    timedOut = false;
    lastPing?: Date = null;

    constructor(private idle: Idle, private keepalive: Keepalive, location: Location, router: Router) {

        // sets an idle timeout of 5 seconds, for testing purposes.
        idle.setIdle(5);

        // sets a timeout period of 5 seconds. after 10 seconds of inactivity, the user will be considered timed out.
        idle.setTimeout(5);

        // sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
        idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);

        idle.onIdleEnd.subscribe(() => this.idleState = 'No longer idle.');

        idle.onTimeout.subscribe(() => {
            this.idleState = 'Timed out!';
            this.timedOut = true;
        });

        idle.onIdleStart.subscribe(() => this.idleState = 'You\'ve gone idle!');
        idle.onTimeoutWarning.subscribe((countdown) => this.idleState = 'You will time out in ' + countdown + ' seconds!');

        // Sets the ping interval to 15 seconds
        keepalive.interval(15);

        keepalive.onPing.subscribe(() => this.lastPing = new Date());

        // Lets check the path everytime the route changes, stop or start the idle check as appropriate.
        router.events.subscribe((val) => {

            this.currentPath = location.path();
            if(this.currentPath.search(/authentication\/login/gi) == -1)
                idle.watch();
            else
                idle.stop();

        });
    }

    reset() {
        this.idle.watch();
        this.idleState = 'Started.';
        this.timedOut = false;
    }
}
person ajay hariyal    schedule 25.09.2019