Это решение, которое я использовал.Я не должен был вызывать sendRedirect () в моем фильтре, так как он никогда не вернет новый JSESSIONID в клиентский браузер.Мне нужно отправить реальный ответ, который убивает старый JSESSIONID Cookie, в противном случае клиентский браузер просто будет пытаться его использовать.Моей первой мыслью было получить cookie-файл JSESSIONID из заголовка запроса, установить срок его действия, а затем включить cookie-файл с истекшим сроком действия в ответ, чтобы клиент действовал по истечении срока действия.Другие пользователи Stackoverflow предположили, что это не было чистым решением, поэтому я отказался от этой идеи.
Я заменил свой метод handleSessionExpired () в Filter
на использование RequestDispatcher
.Это позволит моему Filter
отправить запрос на пользовательскую страницу JSP "ваш сеанс истек".В отличие от перенаправления, RequestDispatcher
отправит правильный ответ клиенту.
Вот основной метод в моем 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 {
filterChain.doFilter(request, response);
}
}
}
Мой handleSessionExpired()
метод оченьпросто.Этот дополнительный вызов метода существует только из-за другого особого варианта использования, который должен обрабатывать мой фильтр (но он не относится к моему первоначальному вопросу).
private void handleSessionExpired(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse)
throws IOException, ServletException {
logger.info("expired session | id: " +
httpServletRequest.getRequestedSessionId());
sendSessionExpiredResponse(httpServletRequest, httpServletResponse);
}
My sendSessionExpiredResponse()
также довольно прост.Вызов getSession()
приведет к созданию нового сеанса (поскольку на данный момент уже нет действительного HttpSession) и JSESSIONID, который будет включен в ответ.Это заботится об очистке устаревшего идентификатора сеанса на стороне клиента.Я установил атрибут запроса «isExpired», чтобы JSP об истечении сеанса знал, что нужно отобразить сообщение о том, что сеанс истек.Я также использую ту же страницу JSP, когда пользователь вручную завершает сеанс, поэтому я использую атрибут, чтобы решить, какой текст отображать на странице.
private void sendSessionExpiredResponse(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse)
throws IOException, ServletException {
httpServletRequest.getSession(true); // force valid session to exist
httpServletRequest.setAttribute("isExpired", true);
RequestDispatcher rd = filterConfig.getServletContext()
.getNamedDispatcher("SessionExpired");
rd.forward(httpServletRequest, httpServletResponse);
}
Вызов getNamedDispatcher()
получает JSP черезмоя запись в web.xml
:
<servlet>
<servlet-name>SessionExpired</servlet-name>
<jsp-file>/SessionExpired.jsp</jsp-file>
</servlet>