RESUMEN:
Configuraremos una aplicación web para añadirle seguridad usando
Spring Security.
Posteriormente configuraremos la aplicación para autenticarnos mediante
Single Sign On ( Usando el servidor
CAS de jasig )
1. - Añadimos seguridad a una aplicación web ( sin CAS )
Primero descargaremos la aplicación demo de
Loom. que nos servirá de base para nuestro ejemplo:
Accedemos a la
página de descargas y nos descargamos la demo:
$ wget http://downloads.sourceforge.net/project/loom/loom/2.1/loomdemo.war
Una vez hayamos descargado el fichero, necesitamos expandirlo para poder modificar la aplicación.
$ mkdir loomdemo
$ cd loomdemo
$ jar xvf ../loomdemo.war
La aplicación
loomdemo está basada en Spring y no viene con seguridad implementada.
Necesitaremos descargar y añadir las librerías relativas a Spring Security
$ cd WEB-INF/lib
$ wget http://www.jarvana.com/jarvana/archive-details/org/springframework/security/spring-security-acl/3.0.3.RELEASE/spring-security-acl-3.0.3.RELEASE.jar http://www.jarvana.com/jarvana/archive-details/org/springframework/security/spring-security-config/3.0.3.RELEASE/spring-security-config-3.0.3.RELEASE.jar http://www.jarvana.com/jarvana/archive-details/org/springframework/security/spring-security-core/3.0.3.RELEASE/spring-security-core-3.0.3.RELEASE.jar http://www.jarvana.com/jarvana/archive-details/org/springframework/security/spring-security-taglibs/3.0.3.RELEASE/spring-security-taglibs-3.0.3.RELEASE.jar http://www.jarvana.com/jarvana/archive-details/org/springframework/security/spring-security-web/3.0.3.RELEASE/spring-security-web-3.0.3.RELEASE.jar
El siguiente paso es modificar el fichero
web.xml de la aplicación para añadirle seguirdad. Editamos el fichero WEB-INF/web.xml y añadimos al parámetro
contextConfigLocation otro fichero de configuración de Spring ( que crearemos a continuación )
spring-security-config.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-config.xml
classpath:spring-security-config.xml
</param-value>
</context-param>
No nos debemos de olvidar de añadir también el filtro de seguridad Spring en el web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Crearemos primero un fichero de configuración de seguridad básico, para comprobar que todo funciona correctamente. Aseguraremos los accesos a
/mortgages/create con el rol
ROLE_USER y a
/support/** con el rol
ROLE_ADMIN. De paso solicitaremos que cualquier acceso se haga a través de
https
$ vim WEB-INF/classes/spring-security-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-autowire="byName">
<security:http auto-config="true" path-type="ant">
<security:intercept-url pattern="/mortgages/create" access="ROLE_USER"/>
<security:intercept-url pattern="/support/**" access="ROLE_ADMIN"/>
<security:intercept-url pattern="/**" requires-channel="https" />
<security:logout logout-url="/logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service properties="/WEB-INF/user.properties"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
Los usuarios, roles y contraseñas los especificamos en el fichero
user.properties
$ vim WEB-INF/user.properties
admin=admin,ROLE_ADMIN,ROLE_USER
user=user,ROLE_USER
Si todo ha ido correctamente, podemos desplegar la aplicación en Tomcat (copiamos la carpeta loomdemo a $CATALINA_HOME/webapps)
Una vez arrancado el Tomcat, podemos acceder a la aplicación :
http://localhost:8080/loomdemo.
Lo primero que vemos es que, tal y como le hemos especificado al requerir un canal seguro ( 8443 a través de https), nos hace automáticamente una redirección:
El siguiente paso es comprobar que funciona la seguridad. Para ello intentamos acceder a una URL protegida
https://localhost:8443/loomdemo/mortgages/create Si todo está correcto, nos aparecerá una ventana solicitándonos el usuario y la contraseña:
Especificando un usuario definido previamente en el fichero user.properites (admin/admin) obtendremos el acceso:
Para poder hacer logout, añadiremos al menú lateral un enlace en donde además mostraremos el username.
Modificamos el fichero leftColumn.tag que se encuentra en WEB-INF/tags:
$ vim WEB-INF/tags/leftColumn.tag
<authz:authorize ifAnyGranted="ROLE_ADMIN,ROLE_USER">
Logged as : <authz:authentication property="principal.username" />
<ul>
<li><l:url href="/logout" >logout</l:url></li>
</ul>
</authz:authorize>
2. - Añadimos SSO - Autentificación por CAS a la aplicación:
El proceso para validar usuarios usando CAS, requiere de un servidor CAS, que es el encargado de comprobar las credenciales que aporta el usuario.
Para nuestro ejemplo, descargamos el servidor CAS de la página de Jasig y creamos el war usando maven
$ wget http://downloads.jasig.org/cas/cas-server-3.4.2.1-release.zip
$ unzip cas-server-3.4.2.1-release.zip
$ cd cas-server-3.4.2.1/cas-server-webapp/
$ mvn package
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 42 seconds
[INFO] Finished at: Mon Sep 06 10:39:11 WEST 2010
[INFO] Final Memory: 32M/58M
[INFO] ------------------------------------------------------------------------
Una vez creado el war, lo desplegamos en Tomcat:
$ target/cas.war $CATALINA_HOME/webapp/.
Comprobamos que se haya desplegado correctamente accediendo a
http://localhost:8080/cas
Este servidor es una demo que autentifica a cualquier usuario siempre que el password sea igual al username. Introducimos admin/admin y validamos:
(*) Para hacer logout, accedemos a http://localhost:8080/cas/logout
En este punto ya tenemos arrancada nuestra aplicación a la que le hemos añadido seguridad y un servidor CAS. El siguiente paso es configurar nuestra aplicación para que se autentifique con el servidor.
Para no modificar el fichero anterior, creamos un fichero de configuración para la autentificación mediante CAS:
spring-security-config-CAS.xml :
Nota: En lugar de usar
localhost usaremos el nombre del servidor; en este caso
myserver
$ vim WEB-INF/classes/spring-security-config-CAS.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<sec:http entry-point-ref="casEntryPoint" auto-config="true" path-type="ant">
<sec:custom-filter before="CAS_FILTER" ref="casSingleSignOutFilter"/>
<sec:custom-filter after="CAS_FILTER" ref="casFilter"/>
<sec:intercept-url pattern="/mortgages/create" access="ROLE_USER"/>
<sec:intercept-url pattern="/support/**" access="ROLE_ADMIN"/>
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:logout logout-success-url="https://myserver:8443/cas/logout" invalidate-session="true" logout-url="/logout" />
</sec:http>
<!-- which application am I authenticating -->
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="https://myserver:8443/loomdemo/j_spring_cas_security_check"/>
<property name="sendRenew" value="false"/>
</bean>
<!-- where do I go when I need authentication -->
<bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://myserver:8443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
<bean id="casSingleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter" />
<bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="casAuthenticationProvider" />
</sec:authentication-manager>
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="userDetailsService" ref="userServices"/>
<property name="serviceProperties" ref="serviceProperties"/>
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://myserver:8443/cas"/>
</bean>
</property>
<property name="key" value="my_password_for_this_auth_provider_only"/>
</bean>
<sec:user-service properties="/WEB-INF/user.properties" id="userServices"/>
</beans>
Ya solo nos queda especificar este fichero en lugar del anterior en el web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-config.xml
classpath:spring-security-config-CAS.xml
</param-value>
</context-param>
Listo !!! .... ahora cuando intentemos acceder a una URL protegida, en lugar de redirigirnos a la antigua página de Login :
Nos redirigirá al servidor CAS :