2009-12-17 24 views
12

Estoy haciendo un foro simple con una serie de Servlets que representan cada uno una página de inicio, tema, postedit, inicio de sesión y lista de usuarios. En algunas de estas páginas hay un enlace que aparece cuando un usuario no está conectado.Redirigir a una página después de un inicio de sesión

Lo que me gustaría lograr es desencadenar una redirección (utilizando forward() en un RequestDispatcher) después de un inicio de sesión para que el el navegador vuelve a la página donde estaba el usuario antes de hacer clic en el enlace de inicio de sesión. Para hacer esto, veo dos soluciones.

La primera solución es tener un HTML Form con un botón de inicio de sesión y un campo invisible que contendrá información que dirá qué página redirigir como Parameter. Esto es factible, pero me gustaría probar algo más.

La segunda solución es agregar un Attribute al session que representa la primera "página" de alguna manera. Esto podría contener una Cadena, pero esto no es diferente de la primera aproximación. Otro giro sería agregar una referencia al HttpServlet y usar instanceof o una variable de cadena estática que podría usarse para identificar el servlet de alguna manera. Sin embargo, esto requeriría crear una clase antecesora común para todos los Servlets.

¿Quizás hay otra solución simple que pueda ver y que sería un buen compromiso? ¿O tal vez una de las soluciones anteriores es perfectamente aceptable?

Respuesta

24

Preferiría la primera sobre la segunda solución. Esta es solicitud información de ámbito y realmente no pertenece a la sesión, solo conduciría a "wtf?" experiencias cuando tiene múltiples ventanas/pestañas abiertas en la misma sesión.

En el enlace a la página de inicio de sesión, sólo tiene que pasar la URL actual como parámetro de la petición:

<a href="/login?from=${pageContext.request.requestURI}">Login</a> 

O si se trata de un formulario de envío a la página de inicio de sesión:

<input type="hidden" name="from" value="${pageContext.request.requestURI}"> 

En el inicio de sesión formulario, transfiéralo a la próxima solicitud como variable oculta:

<input type="hidden" name="from" value="${param.from}"> 

En el servlet de inicio de sesión, utilícelo :

User user = userDAO.find(username, password); 
if (user != null) { 
    request.getSession().setAttribute("user", user); 
    response.sendRedirect(request.getParameter("from")); 
} else { 
    // Show error. 
} 

Bastante simple, ¿no? :)

Algunos pueden sugerir utilizar request.getHeader("referer") para esto dentro del formulario de inicio de sesión en lugar de request.getRequestURI() en el enlace/botón antes de iniciar sesión, pero yo no haría eso ya que esto está controlado por el cliente y no siempre devuelve información confiable . Algunos clientes lo han desactivado o están usando algún software que lo falsifica con un valor no válido, como la mayoría de los productos de Symantec (, tos).

+0

Excelente respuesta, además de que me da una idea de a qué apuntar una vez que se agrega un DAO. –

+0

Si está utilizando seguridad administrada por contenedor, publicar la solicitud en j_security_check no le permitirá hacerlo; en su lugar use el inicio de sesión programático de la versión 3 de Servlet: HttpServletRequest.login – Ryan

+0

Muchas gracias. –

3

Si desea hacer esto con las páginas, su página de inicio de sesión podría mirar el encabezado referer (sic) en la solicitud que lo cargó (request.getHeader("referer")) para ver si es una página en su sitio (si no, o falta el encabezado: use un valor predeterminado de algún tipo). Luego almacenaría esa URL (probablemente usaría un campo oculto, como dijiste, en el formulario de inicio de sesión, pero una sesión var también funcionaría). Cuando se complete el inicio de sesión, emita un redireccionamiento a la URL almacenada.

En estos días, probablemente usaría todo eso como un mecanismo alternativo si no pudiera hacer el inicio de sesión superponiendo un diálogo en la página e iniciando sesión a través de Ajax, y nunca abandonando la página. .


Editar O mejor aún, como señala Bozho, codificar la página de destino en su enlace a la página de inicio de sesión. Aunque es no cierto que IE no establece el encabezado "referer" (sí), el referer no es necesario y se puede deshabilitar, y como ya está creando dinámicamente la página que enlaza al formulario de inicio de sesión, ¿por qué ser vulnerable? a eso si no necesitas serlo

+1

El refere no es necesario y IE no lo configura. Por lo tanto, no es preferible redireccionar a una página predeterminada en 50 +% de los casos – Bozho

+0

IE8 parece devolver el mismo valor de referencia que Firefox. De su respuesta, me imagino que este no es el caso con otras versiones de IE. –

+1

@Bozho: No estoy seguro de a qué se refiere (por así decirlo). Acabo de probarlo para estar seguro: IE6 lo establece, IE7 lo configura, IE8 lo configura. –

1

de: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.pdf

capítulo: Flujo de aplicaciones en el éxito y el fracaso de autenticación

... Si la autenticación es satisfactoria, el objeto de autenticación resultante se situará en el SecurityContextHolder. El AuthenticationSuccessHandler configurado se llamará para redirigir o reenviar al usuario al destino apropiado. De forma predeterminada, se utiliza SavedRequestAwareAuthenticationSuccessHandler, lo que significa que el usuario será redireccionado al destino original que solicitó antes de que se le solicite iniciar sesión. ...

+0

Gracias Nils. He estado experimentando con Spring, así que esto será útil más adelante. –

1

El uso del campo oculto en el formulario es bastante estándar. ¿Por qué intentar reinventar la rueda?

+0

Sí, es una práctica estándar con HTML pero no estaba tan seguro cuando se trata de aplicaciones web. Además, una razón para reinventar la rueda es comprender mejor por qué se necesitaba la rueda en primer lugar;) –

4

Su primer enfoque sugerido es el mejor. Tenga un campo oculto con value=request.getRequestURI() y redirija a ese URI después de iniciar sesión.

El uso de referer no funcionará, porque IE (al menos algunas de sus versiones) no configura el encabezado referer.

Almacenar un parámetro en la sesión provocará un comportamiento extraño si el usuario abre varias pestañas.

Editar: Para ilustrar la mejor pregunta:

some resource -> (requests protected resource) -> (gets forwarded to the login page) -> (should be redirected to the original resource)

mayoría de las respuestas asumen que se hace clic en un botón de "inicio de sesión" enlace /, y luego se abre la página de inicio de sesión. Este es solo un lado de la historia. En ese caso, la URL del recurso original se puede agregar como un parámetro y colocarse en el formulario de inicio de sesión (en un campo oculto).

Pero en el caso de reenviando de un recurso protegido a la página de inicio de sesión, el campo oculto debe contener la URL de solicitud inmediata.

Esto, por supuesto, no es lo que hay en la pregunta, pero eventualmente surgirá como una situación y debería considerarse también.

+0

Um, * ¿qué * versiones? ¿Referencia? Acabo de probar IE6, IE7 e IE8. Todos lo hacen. (No es que no sea mejor codificar el enlace en la URL de la página de inicio de sesión). –

+0

Tener un formulario para codificar el vínculo de retroceso parece excesivo. Simplemente codifíquelo en el enlace de formulario de inicio de sesión como parámetro de consulta. –

+0

La mayoría de los clientes a establecer la cabecera árbitro, pero por supuesto que pueden ser invalidados/definen en blanco en el lado del cliente, por lo que definitivamente me iría a request.getRequestURI() Ben

0

Ok, esto es lo que hice. El inicio de sesión es un proceso de dos pasos con un servlet que muestra un formulario y otro que controla si la combinación de nombre de usuario y contraseña es correcta. Los dos podrían combinarse.

Un parámetro puede ser enviada a través de un formulario o a través de un enlace (JSP no se ha añadido todavía):

out.println("Login <a href='LoginServlet?comeback=home'>here</a><br>"); 

El parámetro es entonces recuperada de la siguiente manera:

String comeback = request.getParameter("comeback"); 

Una vez que el la información de inicio de sesión ha sido revisada, la redirección se puede hacer de la siguiente manera:

RequestDispatcher rd = request.getRequestDispatcher(redirectionPath); 

if(rd != null) 
    rd.forward(request, response); 
Cuestiones relacionadas