Skip to content

j_security_check: Conocer la página original solicitada

18 abril 2009

Como sabéis, podemos añadir autenticación a nuestra aplicación web, de una manera cómoda y simple utilizando j_security_check. Sobre todo usaremos este mecanismo cuando nos interese dotar a nuestra aplicación web de autenticación basada en formulario.

En esta entrada no voy a explicar en detalle cómo funciona j_security_check, pero si voy a comentar algo que nos choca en un principio cuando empezamos a trabajar con este mecanismo.

Bien, vamos a imaginarnos la siguiente situación: Hemos creado nuestra aplicación web y nos interesa dotarla con un mecanismo de autenticación de manera que sólo los usuarios registrados tengan acceso a la zona privada. El esquema de autenticación con formulario que utilizaremos si aplicamos el método j_security_check, es el siguiente:

security-formbasedlogin

Understanding Login Authentication

Por tanto, vamos a necesitar implementar:

  • Una página de login que contendrá nuestro formulario con j_security_check
  • <form method=post action="j_security_check">
    <input type="text"  name= "j_username"/>
    <input type="password"  name= "j_password"/>
    </form>
  • Una página de error donde redireccionaremos al usuario si sus credenciales no son correctas

Ahora hablaremos un poco más de esta página de error que es donde reside una de las mayores incognitas a la hora de trabajar con j_security_check.

Antes, sólo comentar cuál es la forma adecuada para trabajar con la página de login y la página de error. Nosotros como programadores de la aplicación web, debemos tener en cuenta, que nunca, repito nunca, tenemos que redireccionar nuestra aplicación hacia alguna de estas páginas. ¿Por qué? Porque ya se encargará j_security_check de hacerlo.

Es decir, si el usuario entra en la zona privada será j_security_check quien lo redirija a la página de login y si no tiene privilegios, será j_security_check quien lo envíe a la página de error.

Por tanto nosotros, crearemos esas páginas, configuraremos las rutas en nuestro contenedor para que las use j_security_check y nos olvidaremos de ellas en nuestra aplicación web.

Bien, parece que el funcionamiento de la página de login.jsp es bastante claro. Además hay muchos ejemplos en internet que nos muestran cómo crearla y utilizarla y no voy a entrar en ello, con el ejemplo anterior nos sobra.

Sin embargo, la página de error es distinta. Me explico. Cuando el usuario está navegando por nuestra aplicación (zona pública) y decide entrar en una zona restringida, si sus credenciales no son correctos, j_security_check le redireccionará a una página de error (que nosotros habremos diseñado) donde le mostraremos entre otras opciones, la opción de Reintentar.

Y aquí es donde está la gran duda, ¿Cómo sabemos nosotros cuál es la página de la zona privada que había pedido el usuario antes de ser redireccionado desde la página de login.jsp a la página de error.jsp?

Si buscáis formas de que j_security_check os lo indique, vais a encontrar muy muy poco. La opción más sencilla, pero no tan evidente es otra.

La solución que propongo es utilizar la propia request que genera el cliente. En jsp, podemos acceder a los parámetros de la request fácilmente y además podemos acceder a los parámetros de la cabecera también muy fácilmente. Pues listo, la información que buscamos se encuentra en la cabecera HTML que se genera en la request que provoca el cliente antes de ser redireccionado a la página de login y que j_security_check utiliza y actualiza.

Veamos el siguiente esquema, para tratar de ilustrar y comprender lo que digo:

  • Tendremos una página de inicio en html (index.html) desde la que el usuario podrá acceder a todas las páginas privadas de nuestra aplicación
  • Tendremos las páginas privadas: contactos.jsp, cuentas.jsp y bd.jsp
  • En la página de index.html, habrá como mínimo tres hipervínculos referenciando a cada una de las páginas
  • Por otro lado y como siempre que usemos j_security_check, tendremos las páginas de login.jsp y error.jsp (Que recordemos, que para nosotros es como sino existieran y no pudieramos referenciarlas directamente) normalmente en nuestra zona privada

esquemahtml

Imaginad que el usuario va a gestionar sus contactos y hace click en el hipervínculo “Contactos” de la página index.html. Automáticamente, si no hay ninguna sesión activa, j_security_check lo redireccionará a la página de login.jsp. Si sus credenciales son correctas, j_security_check volverá a redireccionar al usuario a la página de contactos.jsp sin que nosotros como programadores hayamos implementado nada. Pero si los credenciales no son correctos, el usuario será redireccionado a la página de error.jsp y es aquí donde nos encontramos con el dilema que planteaba antes. ¿Cómo podemos conocer cual es la página que solicitó el usuario inicialmente (contactos.jsp)? Porque una vez aquí, j_security_check ya no nos proporciona ningún mecanismo de redirección automático.

Y os preguntaréis: “¿Para qué me interesa a mi conocer qué página solicitó el usuario? Lo redirijo a la página index.html nuevamente y listo”

Sí, es una opción, pero queda mucho más elegante, ofrecerle un link al usuario en el que le permitamos volver a escribir su user y password. Y este link debería enlazar directamente con la página que él solicitó anteriormente, no con login.jsp ni error.jsp (Eso jamás :))

Y por esta razón, nos interesa conocer cuál es la página que el usuario ha solicitado previamente.

Lo cierto es que la solución es muy sencilla y muy rápida. Y como comentaba antes, simplemente hace falta obtener un parámetro de la cabecera HTML de la request que el usuario ha generado cuando hizo click en el hipervínculo “Contactos”. Este parámetro es “referer“. Es un parámetro de HTML que permite al cliente especificar, para beneficio del servidor, una URI desde la cual ha obtenido un recurso. Y como en esta ocasión la que genera la request en la página de error es j_security_check, ella ya se habrá preocupado de dejarnos ahí la URI de la página que solicitó el usuario previamente ¡Justo lo que necesitamos!

Asi es que la siguiente pregunta es: ¿cómo genero un link en JSP que obtenga el parámetro Referer de la cabecera HTML y lo establezca como destino? Muy simple:

<a href=<%= response.encodeURL(request.getHeader("referer"))%>>Reintentar...</a>

Y listo.

¿Y tanto jaleo para esto?????

Bueno nunca está de más conocer cosas nuevas no?? 😉

Link | HTML Header field definition

Anuncios
12 comentarios leave one →
  1. Mario permalink
    24 julio 2009 23:08

    Muy util gracias.

  2. Armando permalink
    3 noviembre 2009 16:27

    Hola.

    Gracias por el aporte.

    Sin embargo el problema que tengo ahora.. es el siguiente. Mi pagina de logueo. o mejor mi formulario de logueo, esta en el index, cuando desean loguearse sin intentar acceder a un recurso privado, (solo por querer loguearse. mas adelante pueden querer acceder al recurso) el formulario no sabe a donde redireccionarlo, por lo que intenta poner el la url, …./j_security_check. ¿Como podria hacer para redireccionarlo de alguna forma a la pagina de index nuevamente? aunque seria un problema en el sentido que siempre redireccionaria al index. ¿Una opcion podria ser usando filtros?..

    Se le ocurre algo más?

    la verdad no se como afrontar el problema..

    Muchas gracias por su ayuda..

    • rekkeb permalink*
      4 noviembre 2009 00:43

      Realmente este que planteas es un problema bastante común. j_security_check es un método de identificación muy potente, pero a la vez es muy poco flexible. A penas te permite opciones para salirte de los márgenes que te marca.
      Los filtros, como bien dices, te van a permitir manejar la información de logueo, justo antes o después de que j_security_check la haya procesado. Puede ser una opción.
      Se me ocurre una alternativa, un poco simple y consiste en lo siguiente. Crear una página JSP o HTML privada y oculta, a la cual sólo se tenga acceso desde la página principal y cuya función sea redirigir a la página index.html actualizando la información de sesión con los datos del usuario.
      De esta forma si el usuario se ha logueado correctamente, se llamará a esta página, que se encargará a su vez de devolver la llama a index.html. Si las llamadas las haces utilizando AJAX, puede resultar transparente para el usuario.
      Es una solución muy simple, que puede servir para salir del paso. Ya te digo, que lo que menos me agrada de trabajar con j_security_check es su poca flexibilidad en ciertos temas…

      • Armando permalink
        4 noviembre 2009 16:48

        Hola

        Primero gracias por responder.

        No sé si le entendí bien lo que me quería decir.

        Realmente para la capa de presentación, soy algo malo. Y como el proyecto lo trabajamos con faces y richfaces, (reglas de navegación y otro tanto de cosas) se complica algo el asunto.. Pero le cuento como afrontamos este dilema.. lo que hicimos, fue colocar como protegido el index (que tiene el formulario de logueo). Al ser protegido cuando se intenta acceder a ../aplicacion/index.jsf entonces el de una queda a la espera de logueo, El problema fue que no nos dejaba entrar a otras páginas que eran de acceso público, por lo que añadimos en el login-config.xml una línea para tener usuarios sin autenticación (invitado) y agregamos en nuestro web.xml esa nueva regla de seguridad permitiéndole acceder. Sin embargo nos toco modificar algunos links, por lo de las reglas de navegación.

        A la larga no sé si fue más “complicado” de esta forma, que la que usted planteaba.

        Sin embargo, muchas gracias por tomarse el tiempo de responder

      • rekkeb permalink*
        2 diciembre 2009 13:12

        Realmente la solución que yo proponía, era extremadamente sencilla. En cuanto el sistema se complique, como parece ser tu caso, probablemente, no sea la solución más adecuada.
        Además si como bien dices, ya tenías la página index.jsf en la zona privada, mi solución no te iba a aportar nada nuevo.
        Para mí es un placer responder comentarios y charlar con las personas interesadas en mi blog. Gracias a ustedes por visitar este blog 😀

  3. Edwind permalink
    27 noviembre 2009 17:12

    H0la! muchas gracias por esta info, esta muy buena!

    una pregunta, por casualidad sabes como hacer para trabajar los inicio de sesion entre dos sistemas distintos que usan el mismo jboss? Es decir, tengo un sistema A y un sistema B, quiero que al entrar al sistema A e intentar entrar en el sistema B no tenga que volverme a loguear, sino que sepa cuado tengo la sesion abierta. Esto es posible?

    saludos y gracias

    • rekkeb permalink*
      27 noviembre 2009 18:31

      Pues la verdad, es que nunca me había planteado esa opción. La opción que se me ocurre es utilizar cookies. Las cookies almacenan cierta información que los navegadores pueden utilizar para recuperar sesiones de usuario u operaciones más complejas.
      Prueba a investigar más sobre las cookies que quizás sea una posible solución a lo que planteas.

      Saludos!

    • darrenup permalink
      24 marzo 2010 20:49

      Pues nunca lo he usado, pero lei sobre single sign on y hace lo que tu buscas. Saludos.

  4. 2 diciembre 2009 10:32

    Buenos días,

    He encontrado un pequeño problema con j_security_check. El problema es que cuando quiero acceder a una página protegida, mi intención es hacer que pida la página protegida que pida el usuario, se redireccione a index.jsp. j_security_check me da la página que introduzco por URL. No se si es posible lo que planteo debido a la poca flexibilidad de j_security_check .

    Muchas gracias,

    Un saludo.

    • rekkeb permalink*
      2 diciembre 2009 13:27

      Hola Hugo:

      Según lo que me planteas, deduzco que tu intención es que cuando el usuario trate de loguearse con unos credenciales que no sean correctos, el sistema le lleve nuevamente a la página index.jsp.
      En este caso, la opción más simple que se me ocurre es modificar la página de Error.jsp y añadir una única sentencia de redirección hacia la página index.jsp
      Puedes usar: jsp:forward page=”index.jsp” (Entre los símbolos de menor y mayor que no me deja escribirlos)

      No lo se si era esto lo que buscabas. Si no, ya sabes, aqui estamos 😉

      Saludos!

  5. Sergio permalink
    26 mayo 2011 03:23

    Lo logre hacer con JSP. Y muchas gracias por el choro mareador sirve para entender como funciona Realms.
    Una pregunta. ¿Sabes como hacer lo mismo con JSF? por no he encontrado la forma.
    Muchas gracias.

  6. maria permalink
    26 julio 2012 13:06

    Lo más sencillo es poner en la configuracion del error la página del login:
    /login/form.html
    /login/form.html

    Cuando haya un error te redirigirá a la misma página y si metes bien el login, password te llevará a la página que le pediste.

    Un saludo y gran aporte.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: