Java: Почему сеанс http не разрушается при закрытии вкладки или браузера? - PullRequest
16 голосов
/ 01 апреля 2009

У меня есть следующая реализация HttpSessionlistener

public class SessionListener implements HttpSessionAttributeListener, HttpSessionListener {


public void attributeAdded(HttpSessionBindingEvent event) {
   ...

}


public void attributeRemoved(HttpSessionBindingEvent event) {

    ...
}

public void attributeReplaced(HttpSessionBindingEvent event) {

}

//HttpSesion creation & destruction
public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    //log created time


}

public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    long destroyedTime = System.currentTimeMillis();
    //log destroyed time

}

}

В основном я регистрирую время создания и уничтожения сессии. Но если сеанс длинный (по умолчанию 30 минут), а пользователь тем временем закрывает браузер,

sessionDestroyed 

не называется?

Почему это? Существует ли обходной путь для точного ведения журнала, когда сеанс был уничтожен (когда пользователь закрывает браузер)? Не должно ли это быть проблемой браузера, чтобы убить сессию, когда она закрыта?

Есть ли какой-нибудь интерфейс, который мне нужно реализовать, чтобы это работало?

Спасибо!

Ответы [ 8 ]

39 голосов
/ 01 апреля 2009

Как сервер узнает, когда браузер закрыт или вкладка закрыта? В этот момент браузер ничего не отправляет на сервер.

Это фундаментальная часть HTTP - это протокол запроса / ответа, а не «постоянно открытый разговор», где вы можете сказать, покидает ли одна сторона разговор. Думайте об этом как о серии телеграмм, а не о телефонном звонке - и вы не сможете определить, когда вы получили последнюю телеграмму, которую собираетесь получить.

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

6 голосов
/ 13 июля 2009

ПРИМЕЧАНИЕ: Как прокомментировал jwenting ниже, это вовсе не на 100% безопасно. Если событие onunload не вызывается событием закрытия вкладки или окна браузера, это может произойти сбой.

У меня была та же проблема, и я решил ее с помощью навязчивого события JavaScript:

window.onunload

Позвольте мне кратко объяснить, скажем, у вас есть функция JavaScript, которая отправляет, используя jQuery, текущий идентификатор сеанса в этот сервлет для его аннулирования, например:

function safeexit(){
   $.post("/SessionKillServlet", { SID = <%=session.getId()%> }, function(data){});
}

Чтобы вызвать эту функцию, вам просто нужно связать ее следующим образом:

window.onunload =  safeexit;  //without the ()

Теперь метод safeexit будет вызываться при закрытии окна TAB или BROWSER WINDOW (или в перенаправлении).

1 голос
/ 01 апреля 2009

Если вам нужно уничтожить сеанс при закрытии окна / вкладки браузера, вы можете прикрепить обработчик JavaScript к событию onunload, которое выполняет своего рода AJAX-вызов ресурса, который вызывает уничтожение сеанса.

Обратите внимание, что событие onunload не всегда срабатывает, поэтому оно не является полностью заслуживающим доверия. Одним из надежных способов может быть использование системы «сердцебиение».

1 голос
/ 01 апреля 2009

Объекты сессий живут на сервере и контролируются сервером. Только сервер может создавать или уничтожать сеансы. Таким образом, если клиент закрыт, сеанс живет до его истечения. Клиент может только предложить серверу, что он может уничтожить какую-то сессию. Этот запрос должен быть как-то явным. Следовательно, когда вы закрываете окно браузера, нет неявного запроса к серверу о том, что он должен уничтожить данный сеанс.

1 голос
/ 01 апреля 2009

Без большой работы браузер не сообщает серверу, что окно закрыто, поэтому Java не может знать, когда уничтожить сеанс. Следовательно, истекло время ожидания, и сервер первым узнает, что этот сеанс может быть нарушен.

Вы можете попробовать воспроизвести вызов ajax на событии javascript document.onunload https://developer.mozilla.org/en/DOM/window.onunload но вы должны быть уверены, что пользователь не будет находиться на вашем сайте, когда вы это делаете.

0 голосов
/ 20 мая 2017

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

клиентская сторона:

<script src="jquery path"></script>
<script>
  window.onunload = function(){ $.get("${request.contextPath}/logout"); }
</script>

сторона сервера: создать сопоставление запроса для "/ logout"

public void doGet(HttpServletRequest request, HttpServletResponse) {
  request.getSession().invalidate();
  System.out.println('destroy from logout on unload browser');
}

Следующий код не является обязательным

использовать слушатель сеанса, когда хотите знать, когда сеанс уничтожен

//    in class

import javax.servlet.*;
import javax.servlet.http.*;
public class SesListener implements HttpSessionListener {
  public void sessionCreated(HttpSessionEvent se) {
   System.out.println("Session created...");
  }

  public void sessionDestroyed(HttpSessionEvent se) {
    System.out.println("Session destroyed...");
  }
}

//-----------------------------------------

// in web.xml
<listener>
   <listener-class>SesListener</listener-class>
</listener>
0 голосов
/ 06 марта 2016

вы можете просто проверить, если ваш пользователь сеанса, не равны нулю, как:

if (session.getAttribute("user") != null )
   sessionsetAttribute("user","null");
0 голосов
/ 02 апреля 2009

Как уже упоминал Эрик, событие unload в браузере может вызвать функцию javascript, которая, в свою очередь, может получить доступ к URL через сервлет, который выходит из системы. Вам не нужно ждать фактического ответа от сервлета.

Веб-браузер взаимодействует с сервером по протоколу http, и он не имеет состояния.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...