2009-06-22 245 views
38

Estoy ejecutando una aplicación web en JBoss AS 5. También tengo un filtro de servlet que intercepta todas las solicitudes al servidor. Ahora, quiero redirigir a los usuarios a la página de inicio de sesión, si la sesión ha expirado. Necesito hacer esta comprobación 'isSessionExpired()' en el filtro y necesito redirigir al usuario en consecuencia. ¿Cómo lo hago? Estoy configurando el límite de tiempo de mi sesión en web.xml, como se muestra a continuación:Cómo redirigir a la página de inicio de sesión cuando la sesión ha expirado en la aplicación web Java?

<session-config> 
    <session-timeout>15</session-timeout> 
</session-config> 
+0

Por qué no utilizar un SessionListener y redirigir en la sesión destruido? –

+4

@Mr_and_Mrs_D: porque no hay necesariamente una solicitud HTTP disponible durante la destrucción de la sesión. – BalusC

Respuesta

50

Se puede usar un Filter y hacer la siguiente prueba:

HttpSession session = request.getSession(false);// don't create if it doesn't exist 
if(session != null && !session.isNew()) { 
    chain.doFilter(request, response); 
} else { 
    response.sendRedirect("/login.jsp"); 
} 

El código anterior no se ha probado.

Sin embargo, esta no es la solución más extensa. También debe probar que algún objeto o indicador específico del dominio esté disponible en la sesión antes de suponer que, como una sesión no es nueva, el usuario debe haber iniciado sesión. Sea paranoico!

+0

¿cómo se establece "chain" encima de este código? – MacGyver

+0

Sí, eso es cierto. Ese sería un tercer argumento (valor que se pasa) para el tercer parámetro opcional (para la definición del método) en el método, pero doFilter es un método del objeto "cadena" en el código. ¿Dónde se establece "cadena" sobre esa línea de código en tu código fuente? – MacGyver

+0

No sé a qué se refiere con respecto a los 3er parámetros opcionales. La variable 'chain' se pasa a su implementación de' doFilter', por el contenedor. Está implícito en esta respuesta que el código está dentro del 'doFilter'. –

5

La verificación de la sesión es nueva.

HttpSession session = request.getSession(false); 
if (!session.isNew()) { 
    // Session is valid 
} 
else { 
    //Session has expired - redirect to login.jsp 
} 
+9

Su fragmento es susceptible a excepciones de puntero nulo. Pasar falso a 'getSession' no creará una sesión si no existe y, por lo tanto, devolverá nulo. –

+1

'session! = Null &&! Session.isNew()' debería funcionar;) – Yeti

+0

@Yeti, entonces ¿por qué verificar isNew() en absoluto cuando podemos hacer lo mismo con una comprobación nula? :) – Jaikrat

-2

Cuando los registros de uso en, poner su nombre de usuario en la sesión:

`session.setAttribute("USER", username);` 

A principios de cada página se puede hacer esto:

<% 
String username = (String)session.getAttribute("USER"); 
if(username==null) 
// if session is expired, forward it to login page 
%> 
<jsp:forward page="Login.jsp" /> 
<% { } %> 
+4

El código de copiado no está SECO. Usa un filtro Ver también http://stackoverflow.com/questions/3177733/how-to-avoid-java-code-in-jsp-files – BalusC

+2

¡Solución completamente horrible! – Kong

4

el interior del filtro se inyecte esta JavaScript que será trae la página de inicio de sesión como esta. Si no lo hace, en su llamada AJAX obtendrá la página de inicio de sesión y se agregará el contenido de la página de inicio de sesión.

Dentro de su filtro o redirigir insertar esta secuencia de comandos en respuesta:

String scr = "<script>window.location=\""+request.getContextPath()+"/login.do\"</script>"; 
response.getWriter().write(scr); 
8

también puede hacerlo con un filtro de la siguiente manera:

public class RedirectFilter implements Filter { 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
    HttpServletRequest req=(HttpServletRequest)request; 

    //check if "role" attribute is null 
    if(req.getSession().getAttribute("role")==null) { 
     //forward request to login.jsp 
     req.getRequestDispatcher("/login.jsp").forward(request, response); 
    } else { 
     chain.doFilter(request, response); 
    } 
} 
} 

se puede ver el resto en este tutorial

+0

Esto también puede arrojar una excepción de puntero NULL cuando intenta leer el atributo si getSession devuelve nulo. – Swaprks

+1

También es posible que tenga algunas páginas donde el usuario no ha iniciado sesión. Es decir, páginas de registro donde no obtendrá ninguna función. –

1

Hasta el tiempo de espera de la sesión recibimos una solicitud normal, después de la cual recibimos una solicitud de Ajax. Podemos identificarlo de la siguiente manera:

String ajaxRequestHeader = request.getHeader("X-Requested-With"); 
if ("XMLHttpRequest".equals(ajaxRequestHeader)) { 
    response.sendRedirect("/login.jsp"); 
} 
0

me encontré con esta posible solución:

public void logout() { 
    ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext(); 
    String ctxPath = ((ServletContext) ctx.getContext()).getContextPath(); 
    try { 
     //Use the context of JSF for invalidate the session, 
     //without servlet 
     ((HttpSession) ctx.getSession(false)).invalidate(); 
     //redirect with JSF context. 
     ctx.redirect(ctxPath + "absolute/path/index.jsp"); 
    } catch (IOException ex) { 
     System.out.println(ex.getMessage()); 
    } 
} 
14

Cómo redirigir a la página de acceso cuando la sesión ha caducado en aplicación web de Java?

Esta es una pregunta incorrecta. Debe diferenciar entre los casos "El usuario no ha iniciado sesión" y "La sesión ha expirado". Básicamente, desea redireccionar a la página de inicio de sesión cuando el usuario no está conectado. No cuando la sesión ha expirado. La respuesta actualmente aceptada solo marca HttpSession#isNew(). Pero esto obviamente falla cuando el usuario ha enviado más de una solicitud en la misma sesión cuando la JSP crea implícitamente la sesión o no. P.ej. cuando solo presionas F5 en la página de inicio de sesión.

Como dije, en su lugar deberías verificar si el usuario está conectado o no. Dado el hecho de que está haciendo este tipo de preguntas mientras los marcos de autenticación estándar como j_security_check, Shiro, Spring Security, etc. ya administran esto de forma transparente (y por lo tanto no habría necesidad de hacer este tipo de preguntas sobre ellos), eso solo puede significa que está utilizando un enfoque de autenticación de cosecha propia.

Suponiendo que usted está almacenando el usuario que ha iniciado sesión en la sesión de inicio de sesión en alguna servlet, como a continuación:

@WebServlet("/login") 
public class LoginServlet extends HttpServlet { 

    @EJB 
    private UserService userService; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); 
    } 

    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String username = request.getParameter("username"); 
     String password = request.getParameter("password"); 
     User user = userService.find(username, password); 

     if (user != null) { 
      request.getSession().setAttribute("user", user); 
      response.sendRedirect(request.getContextPath() + "/home"); 
     } else { 
      request.setAttribute("error", "Unknown login, try again"); 
      doGet(request, response); 
     } 
    } 

} 

A continuación, puede comprobar que, en un inicio de sesión filter, como a continuación:

@WebFilter("/*") 
public class LoginFilter implements Filter { 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {  
     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 
     HttpSession session = request.getSession(false); 
     String loginURI = request.getContextPath() + "/login"; 

     boolean loggedIn = session != null && session.getAttribute("user") != null; 
     boolean loginRequest = request.getRequestURI().equals(loginURI); 

     if (loggedIn || loginRequest) { 
      chain.doFilter(request, response); 
     } else { 
      response.sendRedirect(loginURI); 
     } 
    } 

    // ... 
} 

No hay necesidad de juguetear con los frágiles controles HttpSession#isNew().

2

Debe implementar la interfaz HttpSessionListener, el servidor notificará el tiempo de espera de la sesión.

les gusta esto;

import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 

public class ApplicationSessionListener implements HttpSessionListener { 

public void sessionCreated(HttpSessionEvent event) { 
    System.out.println("Session Created"); 
} 

public void sessionDestroyed(HttpSessionEvent event) { 
    //write your logic 
    System.out.println("Session Destroyed"); 
    } 
} 

Comprobar este ejemplo para una mejor comprensión

http://www.myjavarecipes.com/how-to-catch-session-timeouts/

Cuestiones relacionadas