Перенаправление после истечения времени ожидания HttpSession
Я смотрел много сообщений по этой теме, но не смог найти решение, которое работает в моем случае.
Я использую Java EE 6 с JSF 2.0 (развернутый на JBoss AS 7.1)
В моем web.xml
у меня есть:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
и я хотят, чтобы пользователь был перенаправлен на страницу входа в систему, когда сеанс автоматически отключается.
что я пробовал:
Подход 1: использование фильтра
Я пробовал следующий фильтр:
@WebFilter()
public class TimeOutFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
System.out.println("filter called");
final HttpServletRequest req = (HttpServletRequest) request;
final HttpSession session = req.getSession(false);
if (session != null && !session.isNew()) {
chain.doFilter(request, response);
} else {
System.out.println("Has timed out");
req.getRequestDispatcher("/logon.xthml").forward(request, response);
}
}
@Override
public void destroy() {
}
}
В web.xml
я пробовал
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
и
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Фильтр работает так, как он вызывается при каждом запросе (ведение журнала "fiter called" в консоли). Однако он не вызывается, когда сеанс заканчивается.
Подход 2: HttpSessionLister
Я попытался использовать HttpSessionListerner
. Метод, получивший следующую подпись:
public void sessionDestroyed(HttpSessionEvent se) {
}
Я не смог перенаправить на определенную страницу. Когда я хочу перенаправить пользователя, я обычно использую NavigationHandler
из FacesContext
, но в этом случае нет FacesContext
(FacesContext.getCurrentInstance()
возвращает null
).
В соответствии с этим сообщением HttpListener не может перенаправить пользователя, потому что он не является частью запроса.
Вопрос
Каков наилучший способ решить эту проблему? Что я могу сделать, чтобы один из двух вышеупомянутых подходов работал?
Ответы
Ответ 1
Вы не можете отправить ответ HTTP, пока клиент не отправляет HTTP-запрос. Просто как тот. Вот как работает HTTP. В противном случае Интернет выглядел бы очень по-другому, если бы какой-либо веб-сайт смог ненавязчиво направить ответ HTTP без запроса клиента на него.
Основание на основе JavaScript на основе активности клавиатуры и мыши на клавиатуре, например, как указано здесь, или заголовка meta refresh
, например, как ответ здесь было бы решением, если у вас в основном одностраничный webapp (таким образом, вы фактически не используете область сеанса, но область видимости), но это не сработает, открывать страницу в нескольких вкладках/окнах в том же сеансе.
Websockets теоретически - правильное решение для чего-то нажать на клиента, но это требует, в свою очередь, активного сеанса. Проблема с куриным яйцом. Кроме того, он не будет работать в старых браузерах, которые в настоящее время все еще относительно широко используются, поэтому в настоящее время он просто должен использоваться для прогрессивного улучшения.
Лучше всего просто определить страницу с ошибкой, которая касается случая, когда enduser вызывает действие во время истекшего сеанса. См. Также javax.faces.application.ViewExpiredException: просмотр не удалось восстановить.
Ответ 2
В HttpSessionListerner вы не можете отправить ответ пользователю. Одним из хороших способов добиться этого является опрос, браузер отправляет HTTP-запросы через регулярные промежутки времени и сразу получает ответ.
Есть много способов сделать это:
-
Вы можете использовать простой старый javascript для опроса: это будет работать в кросс-браузере.
функция refresh() {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout (обновление, 5000);
-
Вы можете использовать веб-сокеты. Спецификация веб-сокета присутствует по ссылке ниже:
http://dev.w3.org/html5/websockets/
Ответ 3
Я понимаю, что вы используете java-EE6 и JSF, но если вы можете попробовать использовать JSP-код или преобразовать этот код ниже для работы в сервлете. Предполагая, что вы используете имя пользователя для проверки сеанса, после установки тайм-аута сеанса в файле web.xml. Обратите внимание, что код JSP и код сервлета похожи.
Ваш код для проверки сеанса может выглядеть следующим образом: (JSP Format)
Если имя пользователя является основным ключом в вашей базе данных.
<%
String un = (String)session.getAttribute("un");
if(un == null){
response.sendRedirect(login page);
return;
}else{
code to process login form
}
%>
Код сервлета может выглядеть так:
String un = (String)session.getAttribute("un");
if(un == null){
response.sendRedirect(loginPage);
}
Ответ 4
Вы можете использовать фильтр и выполнить следующий тест:
HttpSession session = request.getSession(false);
if(session != null && !session.isNew()) {
chain.doFilter(request, response);
}
else {enter code here
response.sendRedirect("/login.jsp");
}