Spring Security, problemas con proxy Apache

He participado en un desarrollo web donde me ha tocado configurar un proxy con el servidor apache (mis últimos artículos han sido sobre este tema), la idea es exponer una aplicación web en Java por medio de un proxy con Apache.

Tengo una aplicación Java que utiliza Spring Security y todo funciona de maravilla cuando entras a la página web, sin embargo al colocar el proxy frente a este servidor Spring Security puede provocar algunos problemas:

Problema 1: Login, Authentication method not supported: GET

A la fecha no entiendo como puede ser esto posible, dentro del form está estrictamente definido que los datos se envían por POST y no por GET:

Este es el formulario:

    <form action="my_custom_login" method="POST">
        <!-- ommited input fields ...-->
    </form>

Nota: por defecto la url de espring es j_spring_security_check, yo la modifique por my_custom_login.

Pero al pasar por el proxy parece que el apache lo modifica y Spring Security no puede procesar los datos y muestra el mensaje:

Authentication method not supported: GET

Y es más que claro el error, los datos están llegando por GET al servidor Java. Spring  por defecto te pide obligatoriamente que utilices POST, pero curiosamente este error solo se presenta con el login de Spring, todos los otros formularios que utilizan POST funcionan bien.

Solución

Agregar dentro de la configuración del apache una regla que permita sobreescribir este comportamiento, debes activar el mod_rewrite  y agregar lo siguiente al httpd.conf:

<VirtualHost *:80>
        ServerName labs.orbitalzero.com

        #
        # Portal Java Web App
        #
        ProxyPass / ajp://localhost:8009/MyApp/
        ProxyPassReverse / ajp://localhost:8009/MyApp/
        ProxyPassReverseCookiePath /MyApp /

        ProxyRequests off 
        ProxyPreserveHost On

        <proxy >
                Order deny,allow
                Allow from all
        </proxy>
        # FIX For Spring Security
        RewriteEngine on
        RewriteRule ^/MyApp/(.*)$ ajp://localhost:8009/MyApp/$1 [P,L]
</VirtualHost>

La primer parte define que el proxy filtre el tráfico a nuestra aplicación por medio del ProxyPass, ProxyPassReverse y ProxyPassReverseCookiePath.

La parte más importante es el RewriteEngine y el RewriteRule, la regla indica que la dirección url para el login de la aplicación va a ser sobre escrita por la ruta exacta del servidor Java (ojo porque utiliza el protocolo ajp, debes tenerlo activado en tu servidor Java).

Listo con esto ya debe funcionar correctamente el login.

Problema 2: Contexto en la URL, problemas con las rutas.

Supongamos que tienes una página web en la cual entras ip o por un dominio,  digamos algo como http://labs.orbitalzero.com y cuando entras al sitio en la barra de direcciones vas a ver algo como esto:

Pero si solicitas una página verás algo así http://labs.orbitalzero.com/pagina1.html :

Hasta aquí todo normal, el problema se refleja  después de pasar el login con el Spring Security, ya que al redireccionar va a colocar el nombre del contexto de tu aplicación web como prefijo en la url:

Lo extraño es que en el mejor de los casos tu aplicación va a funcionar sin problemas si el desarrollo cuenta con un buen manejo de rutas relativas y absolutas, en mi caso me han pedido algo bastante complejo por lo cual tuve que manejar una mezcla de ambas, pero si el tuyo no es así… el contexto de la aplicación /MyApp/ que coloca Spring te va a provocar muchos problemas.

Solución

Checar el mnejo de rutas en tu aplicación y con la solución anterior se resuelve este problema:

<VirtualHost *:80>
        # .... ommited previous lines
        # FIX For Spring Security
        RewriteEngine on     
        RewriteRule ^/MyApp/(.*)$ ajp://localhost:8009/MyApp/$1 [P,L]      
</VirtualHost>

Guardas y reinicias el servidor apache, ahora después de haber pasado por el login todas las rutas serán redireccionadas de forma correcta a excepción de las rutas anidadas:

Aquí dejo un ejemplo de configuración completo del httpd.conf, tienen otros datos porque utiliza un certificado con SSL.

Saludos!

Referencias

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