Java: Почему HTTP-сессия не уничтожается при закрытии вкладки или браузера?
У меня есть следующая реализация 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
не называется?
Почему?
Существует ли временное решение для регистрации точно, когда сеанс был уничтожен (когда пользователь закрывает браузер)? Должна ли быть проблема браузера, чтобы убить сеанс, когда он закрыт?
Есть ли какой-либо интерфейс, который я должен реализовать для этого?
Спасибо!
Ответы
Ответ 1
Как сервер знал бы, когда браузер закрыт или вкладка закрыта? В этот момент браузер ничего не отправляет на сервер.
Это фундаментальная часть HTTP - это протокол запроса/ответа, а не "постоянно открытая беседа", где вы можете сказать, покидает ли одна из них беседа. Думайте об этом как о серии телеграмм, а не о телефонном звонке, и вы не можете сказать, когда получите последнюю телеграмму, которую вы собираетесь получить.
Вам нужно разработать свой путь вокруг этого - чтобы избежать необходимости знать, когда браузер закрыт. Есть некоторые уродливые хаки, чтобы обойти это, что делает AJAX опросом сервера с сообщением heartbeat, например, но изменение дизайна является лучшим решением.
Ответ 2
ПРИМЕЧАНИЕ. Как показано ниже, 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 (или в перенаправлении).
Ответ 3
При большой работе браузер не сообщает серверу, что окно закрыто, поэтому Java не может знать, когда нужно уничтожить сеанс. Следовательно, тайм-аут на месте и является первым, когда сервер знает, что этот сеанс может быть удален.
Вы можете попробовать и сыграть ajax-вызов в событии javascript document.onunload
https://developer.mozilla.org/en/DOM/window.onunload, но вы должны быть уверены, что пользователь еще не находится на вашем сайте, когда вы это сделаете.
Ответ 4
Объекты сеанса живут на сервере и контролируются сервером. Только сервер может создавать или уничтожать сеансы. Поэтому, если клиент закрыт, сеанс продолжается до истечения срока его действия. Клиент может только предложить серверу, чтобы он мог уничтожить какой-либо сеанс. Этот запрос должен быть каким-то образом явным. Следовательно, когда вы закрываете окно браузера, на сервере нет неявного запроса, информирующего о том, что он должен уничтожить данный сеанс.
Ответ 5
Если вам нужно, чтобы сеанс был уничтожен, когда окно/вкладка браузера закрыто, вы можете присоединить обработчик JavaScript к событию onunload, которое делает какой-то вызов AJAX ресурсу, который вызывает kill session.
Обратите внимание, что событие onunload не всегда срабатывает, поэтому оно не полностью заслуживает доверия. Одним из надежных способов может быть использование системы "сердцебиение".
Ответ 6
Как сказал Эрик, событие разгрузки в браузере может вызвать функцию javascript, которая, в свою очередь, может получить доступ к URL-адресу через сервлет, который выйдет из системы. Вам не нужно ждать ответа от сервлета.
Веб-браузер взаимодействует с сервером через протокол http и не имеет апатридов.
Ответ 7
есть некоторые хаки для знает
использовать сессионный прослушиватель, когда хотите знать, когда был уничтожен сеанс
// 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>
следующий код для уничтожения сеанса, когда пользователь закрывает браузер
клиентская сторона:
<script src="jquery path"></script>
<script>
window.onunload = function(){ $.get("${request.contextPath}/logout"); }
</script>
сторона сервера: создать сопоставление запроса для "/logout"
public void doGet(HttpServletRequest request, HttpServletResponse) {
request.getSession().invalidate();
}
Ответ 8
вы можете просто проверить, не является ли ваш пользователь сеанса нулевым:
if (session.getAttribute("user") != null )
sessionsetAttribute("user","null");