2013-03-22 17 views
10

Przeglądałem wiele postów na ten temat, ale nie mogłem znaleźć rozwiązania, które działa w moim przypadku.Przekierowanie po przekroczeniu czasu HttpSession

używam Java EE 6 z JSF 2.0 (rozmieszczony na JBoss AS 7.1)

W moim web.xml mam:

<session-config> 
     <session-timeout>1</session-timeout> 
    </session-config> 

i Chcę użytkownik zostanie przekierowany na stronę logowania gdy sesja automatycznie przekroczy limit czasu.

co próbowałem:

Podejście 1: stosując filtr

Próbowałem następujący filtr:

@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() { 
    } 
} 

W web.xml Próbowałem

<filter-mapping> 
    <filter-name>TimeOutFilter</filter-name> 
    <url-pattern>*.xhtml</url-pattern> 
</filter-mapping> 

i

<filter-mapping> 
    <filter-name>TimeOutFilter</filter-name> 
    <servlet-name>Faces Servlet</servlet-name> 
</filter-mapping> 

Filtr działa jak nazywa się na każde żądanie (rejestrowanie „fiter nazywany” w konsoli). Jednak nie jest wywoływana, gdy sesja przekroczyła limit czasu.

Podejście 2: HttpSessionLister

Próbowałem użyć HttpSessionListerner. Metoda nazywa się o następującym podpisie:

public void sessionDestroyed(HttpSessionEvent se) { 
} 

Nie mogłem przekierować do konkretnej strony. Kiedy chcę przekierować użytkownika, zwykle używam NavigationHandler z FacesContext, ale w tym przypadku nie ma potrzeby powrotu do stanu sprzed FacesContext (FacesContext.getCurrentInstance()).

Zgodnie z tym post, HttpListener nie może przekierować użytkownika, ponieważ nie jest częścią żądania.

Pytanie

co jest najlepszym sposobem, aby przejść do rozwiązania tego problemu? Co mogę zrobić, aby jedno z dwóch wyżej wymienionych podejść zadziałało?

+1

pokrewne: http://stackoverflow.com/q/ 4992526/1065197 –

+0

@ LuiggiMendoza: Ciekawe dzięki. Chociaż nigdy nie widziałem "ViewExpiredException" i chciałbym, jeśli to możliwe, przekierować na stronę logowania bez konieczności klikania przez użytkownika. – phoenix7360

+0

Potrzebna jest jakaś forma odpytywania po stronie klienta, aby uruchomić 302 po stronie serwera. bicie serca ... –

Odpowiedz

15

Nie można wysłać odpowiedzi HTTP, o ile klient nie wyśle ​​żądania HTTP. Proste. Tak właśnie działa HTTP. W przeciwnym razie Internet wyglądałby zupełnie inaczej, gdyby jakakolwiek strona internetowa mogła wywoływać w niezamierzony sposób odpowiedź HTTP bez żądania klienta.

javascript oparte tętno na podstawie aktywności klawiatura/mysz klienta jak jak odpowiedział here lub meta refresh nagłówek takiego jak odpowiedział here byłoby rozwiązanie, jeśli masz w zasadzie pojedynczą stronę webapp (w ten sposób, jesteś skutecznie nie używając zakresu sesji, ale zakres widoku), ale to nie będzie działać dobrze, jeśli strona jest otwarta w wielu kartach/oknach w tej samej sesji.

Websockets jest teoretycznie właściwym rozwiązaniem, aby przekazać coś klientowi, ale wymaga to z kolei aktywnej sesji. Problem z kurczakiem i jajkiem. Ponadto nie działałoby to w starszych przeglądarkach, które są obecnie stosunkowo często używane, więc obecnie powinny być jedynie używane do stopniowego ulepszania.

Najlepiej jest po prostu zdefiniować stronę błędu, która zajmuje się sprawą, gdy użytkownik wywołuje akcję, gdy sesja wygasła. Zobacz także javax.faces.application.ViewExpiredException: View could not be restored.

+1

Widzę teraz moje nieporozumienie. Zamiast automatycznie przekierowywać użytkownika, potrzebuję czegoś, aby poinformować użytkownika, czy wykona akcję po przekroczeniu limitu czasu sesji. – phoenix7360

-1

Rozumiem, że używasz java-EE6 i JSF, ale jeśli możesz spróbować użyć kodu JSP lub przekonwertować poniższy kod, aby działał w serwlecie. Zakładając, że używasz nazwy użytkownika do sprawdzenia sesji, po ustawieniu limitu czasu sesji w pliku web.xml. Zwróć uwagę, że kod JSP i kod serwletu są podobne. Twój kod do sprawdzania poprawności sesji może wyglądać następująco: (Format JSP) Jeśli nazwa użytkownika służy jako klucz podstawowy w bazie danych.

<% 
    String un = (String)session.getAttribute("un"); 

    if(un == null){ 
    response.sendRedirect(login page); 
    return; 
}else{ 
     code to process login form 
} 
    %> 

Servlet kod mógłby wyglądać ten

String un = (String)session.getAttribute("un"); 
if(un == null){ 
    response.sendRedirect(loginPage); 
} 
0

W HttpSessionListerner nie można wysyłać odpowiedzi na Użytkownika. Dobrym sposobem na osiągnięcie tego jest odpytywanie, przeglądarka wysyła żądania HTTP w regularnych odstępach czasu i natychmiast otrzymuje odpowiedź.
Istnieje wiele sposobów, aby to zrobić:

  1. Można używać zwykłego starego JavaScript do sondowania: To będzie pracować w środowisku przeglądarki krzyżowej.

    funkcję odświeżania() {

    // make Ajax call here, inside the callback call: 
    
    setTimeout(refresh, 5000); 
    
    // ... 
    

    }

    // initial call, or just call refresh directly 
    

    setTimeout (odświeżania, 5000);

  2. Można używać gniazd internetowych. Specyfikacja websocket jest obecny na poniższy link:

    http://dev.w3.org/html5/websockets/

-1

Można użyć filtru i wykonaj następujące czynności Test:

HttpSession session = request.getSession(false); 
if(session != null && !session.isNew()) { 
    chain.doFilter(request, response); 
} 
else {enter code here 
    response.sendRedirect("/login.jsp"); 
} 
Powiązane problemy