Я разрабатываю веб-приложение Java, которое будет работать в защищенной интрасети и не требует входа пользователя. Однако приложение сохраняет диалоговое состояние в HttpSession
. Пользовательский ввод не сохраняется в базе данных, пока они явно не нажали кнопку сохранения на каком-то этапе разговора. До тех пор их ввод сохраняется в объекте HttpSession
. Если их сеанс истекает, пользователь должен быть перенаправлен на страницу, которая сообщает им о завершении сеанса.Как заставить клиентский браузер останавливать запрос на истекший идентификатор сеанса?
Это прекрасно работает, за исключением проблемы с перенаправлением. Когда пользователь позволяет сеансу сидеть без дела дольше, чем время, указанное в <session-timeout>
, сеанс истекает, как ожидалось. Тем не менее, моя попытка перенаправить пользователя на простую страницу «Ваш сеанс истекла», похоже, имеет неприятные последствия. Переадресация работает нормально, но если пользователь не закрывает все открытые окна браузера на своем рабочем столе (а не только те, которые были открыты для моей страницы веб-приложения), они будут постоянно перенаправляться на страницу с истекшим сроком действия.
Вот мои ограничения:
- Клиентские рабочие станции используют Internet Explorer. Это общеорганизация и не изменится в ближайшее время.
- У пользователей будут отдельные экземпляры IE на рабочем столе как часть их обычного рабочего процесса. Говорить им закрыть все экземпляры IE не приемлемо.
- не используя какие-либо компоненты AJAX в этом веб-приложение
Я реализовал редирект с Java Servlet Filter
. Вот соответствующие фрагменты кода:
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
Validate.notNull(filterConfig);
Validate.isTrue(request instanceof HttpServletRequest);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestedSessionId = httpServletRequest.getRequestedSessionId();
logger.info("requestedSessionId: " + requestedSessionId);
HttpSession httpSession = httpServletRequest.getSession(false);
if (requestedSessionId == null) {
// No need to do anything here if no session exists yet
logger.debug("No session exists yet");
filterChain.doFilter(request, response);
} else {
if (httpSession == null) {
Validate.isTrue(response instanceof HttpServletResponse);
HttpServletResponse httpServletResponse =
(HttpServletResponse) response;
handleSessionExpired(
httpServletRequest,
httpServletResponse);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Session OK | requested URL: " +
httpServletRequest.getRequestURL().toString());
}
filterChain.doFilter(request, response);
}
}
}
}
private void handleSessionExpired(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse)
throws IOException {
logger.warn("expired session | id: " +
httpServletRequest.getRequestedSessionId());
String expirationPageURL =
httpServletRequest.getContextPath() + "/" +
"SessionExpiredNotification.html";
httpServletResponse.sendRedirect(expirationPageURL);
}
SessionExpiredNotification.html
страница предназначается, чтобы быть в конце строки. Пользователь должен закрыть это окно браузера и открыть новый, если они хотят начать новый разговор. Проблема в том, что новое окно браузера по-прежнему хочет использовать значение старого идентификатора сеанса, связанное с недействительным сеансом, когда у пользователя есть другие экземпляры Internet Explorer, открытые на рабочем столе. Это не относится к IE, поскольку я подтвердил, что Firefox ведет себя точно так же.
Когда этот код будет достигнут в моем Filter
:
String requestedSessionId = httpServletRequest.getRequestedSessionId();
logger.info("requestedSessionId: " + requestedSessionId);
Я могу видеть, что браузер клиентской стороны все еще держится на стоимость старой идентификатору сессии и просил его снова и снова.
Я не уверен, что это актуально, но мой контейнер для веб-приложений Tomcat 6.x.
МОЙ ВОПРОС:
Как веб-сервер приложений сигнализировать рабочей станции клиента, что идентификатор сеанса больше не действует таким образом, что клиент будет отказаться от него?
мне нужно пользователю, чтобы увидеть простую страницу, которая говорит им, старая сессия истекла и их неспасенный вход был потерян до того они начинают новый сеанс. Если я вызову getSession (true), то разве он не будет продолжать новую беседу без каких-либо указаний на то, что последний был отброшен? –
Нет, это создаст новый сеанс для пользователя, на который будет отвечать контейнер сервлета, отправив обновленному cookie JSESSIONID пользователю. Ваше перенаправление на SessionExpiredNotification.html все равно будет работать. –
@matt_b ОК, я внесу некоторые изменения и попробую по-своему –