Implementando SSO con CAS: ejemplo práctico

14
40999

Implementando SSO con CAS: ejemplo práctico

0. Índice de
contenidos.

1. Entorno

Este tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Mac Book Pro 17″ (2,6 Ghz Intel Core
    i7, 8 GB
    DDR3)
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.4
  • Spring MVC Portlet 3.0.4
  • Maven 2.2.1
  • Eclipse 3.6 (Helios) con M2Eclipse
  • CAS Server 3.4.2.1
  • CAS Client 3.2.0

2. Introducción

Ya vimos hace tiempo las bondades de CAS en el tutorial Introducción a CAS donde veíamos también como se instalaba y su funcionamiento más básico.

En esta oportunidad vamos a ver cómo podemos securizar dos aplicaciones web distintas con CAS, permitiendo que al logarnos en una el acceso a la otra no solicite nuevamente las credenciales.

3. Creación de las aplicaciones web a securizar

Lo primero que vamos a hacer es crear dos aplicaciones web muy sencillitas gracias a la ayuda de Maven. Para ello como de costumbre escribimos en un terminal mvn archetype:generate, seleccionamos el arquetipo web (TIP: suele estar 3 más abajo del de por defecto, es decir, si por defecto sale el 109 pues suele ser el 112, pero mejor comprobadlo) e introducimos los siguientes datos para la primera aplicación:

  • Versión del arquetipo: 1.0
  • groupId: com.autentia
  • artifactId: cas-example-1
  • versión: 1.0-SNAPSHOT
  • package: com.autentia

Y lo mismo para la segunda pero cambiando el artifactId por cas-example-2.

Ahora importamos los proyectos a Eclipse gracias al plugin de m2Eclipse, y simplemente editamos el fichero index.jsp que se crea por defecto, para poner un texto que diga «Esto es cas-example-1» en el caso de la primera aplicación y «Esto es cas-example-2» en el caso de la segunda aplicación, a fin de distinguirlos cuando los despleguemos. Además cada uno de ellos va a llevar una sentencia que recupera el usuario logado de la request, este es el contenido para el primer ejemplo:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>Cas Example 1
</head>
<body>

  <p>Esto es el ejemplo de CAS número 1</p>

  <p>Este es el usuario logado: <%=request.getRemoteUser() %></p>

</body>
</html>

Venga ahora vosotros el ejemplo 2.

4. Configuración del servidor de CAS para permitir el SSO

Una de las primeras cosas que deben quedar claro en la implementación de un SSO con CAS es que sólo puede funcionar a través de un canal seguro, es decir, que tendremos que configurar nuestro Tomcat para habilitar el protocolo HTTPS.

Para ello antes de nada necesitamos un certificado. Para este tutorial nos valdrá con un «dummy» el cual vamos a crear abriendo un terminal y siguiendo los siguientes pasos:

  1. Situarnos en el directorio JAVA_HOME/bin

  2. Generar la key de nuestro certificado, para ello ejecutar: sudo keytool -genkey -alias tomcat -keyalg RSA

    NOTA: La keypass changeit es la de por defecto para Mac

    Esto hace que el sistema pregunta una serie de datos:

    • Enter keystore password: changeit (Válido para Mac)
    • What is your first and last name?: raguilera.com (Aquí lo que pide realmente es un nombre de dominio, no pongais vuestro nombre y dos apellidos porque va a ser un dominio muy largo ;-). Tampoco es aconsejable poner localhost, siempre podéis mapear un nombre de dominio con la dirección 127.0.0.1 en el fichero /etc/hosts de vuestras máquinas).
    • What is the name of your organizational unit?: Desarrollo (Se refiere al departamento)
    • What is the name of your organization? Autentia (Se refiere al nombre de la empresa)
    • What is the name of your City or Locality?: Alcalá de Henares (Capital del imperio español cuando no se ponía el sol)
    • What is the name of your State or Province?: Madrid
    • What is the two-letter country code for this unit?: ES
    • En este momento aparece un resumen con los datos introducidos al que tendremos que responder afirmativamente para que la creación de la key tenga éxito.
  3. Exportar el certificado a un fichero, para ello ejecutamos: sudo keytool -export -alias tomcat -file server_cas.crt. Nos pedirá la contraseña que es changeit y si todo es correcto nos responderá afirmativamente a la creación del fichero.

  4. Importamos el certificado al almacén de certificados de Java, asegurándonos de que estamos situados en la versión de Java que está utilizando nuestro Tomcat. Para ello ejecutamos: sudo keytool -import -alias tomcat -file server_cas.crt -keystore ../lib/security/cacerts. Nos pregunta si queremos confiar en este certificado, le decimos que si y ya está.

El siguiente paso es editar el fichero TOMCAT_HOME/conf/server.xml para descomentar las líneas que se refieren al HTTPS y dejarlas de esta forma:


Lo más importante de esta configuración es definir el puerto y la localización del fichero .keystore, que en general se crea como un archivo oculto dentro de la carpeta del usuario.

5. Configuración de las aplicaciones web

La única configuración que requiere CAS es editar el fichero web.xml para incluir los siguientes filtros:

<filter>
  <filter-name>CAS Authentication Filter</filter-name>
  <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
  <init-param>
    <param-name>casServerLoginUrl</param-name>
    <param-value>https://raguilera.com:8443/cas/login</param-value>
  </init-param>
  <init-param>
    <param-name>service</param-name>
    <param-value>http://raguilera.com:8080/cas-example-1</param-value>
  </init-param>
</filter>

<filter>
  <filter-name>CAS Validation Filter</filter-name>
  <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
  <init-param>
    <param-name>casServerUrlPrefix</param-name>
    <param-value>https://raguilera.com:8443/cas/</param-value>
  </init-param>
  <init-param>
    <param-name>service</param-name>
    <param-value>http://raguilera.com:8080/cas-example-1</param-value>
  </init-param>
</filter>

<filter>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>CAS Authentication Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Esta es la explicación de cada uno de los filtros:

  • CAS Authentication Filter: se encarga de detectar si el usuario está logado, en caso contrario redirecciona el flujo a la URL especificada en el parámetro «casServerLoginUrl». En el parámetro «service» le indicamos la URL donde queremos redireccionar el flujo una vez el usuario haya sido correctamente autenticado por CAS. En resumen, este filtro le asigna un ticket al usuario correctamente logado.
  • CAS Validation Filter: se encarga de validar que el ticket que aporta el usuario es válido es decir que lo tiene asignado y no ha expirado. Para ello requiere que especifiquemos el sufijo por el que empieza nuestro CAS en el parámetro «casServerUrlPrefix» y le indiquemos el mismo «service» que en la autenticación si no queremos que nos de un error de que el ticket proporcionado no corresponde con el servicio.
  • CAS HttpServletRequest Wrapper Filter: una vez el ticket es validado este filtro se encarga de «actualizar» la request con los datos de usuario logado para que podamos recuperarlos interrogando a la request con la sentencia request.getRemoteUser()

Cada aplicación tiene que hacer referencia a las dependencias cas-client-core-3.2.0.jar y commons-logging-1.1.1.jar o si no introducidlas dentro de la carpeta TOMCAT_HOME/lib.

6. Probando el resultado

En mi caso las dos aplicaciones van a correr en el mismo Tomcat que el servidor de CAS, por lo que para probar el resultado tenemos que desplegar las dos aplicaciones en este servidor y arrancarlo.

Lo siguiente será abrir un navegador y poner la siguiente URL: http://raguilera.com:8080/cas-example-1. Tendremos que ver como haciendo esto el navegador nos redirecciona a la URL de login de CAS para que introduzcamos unas credenciales correctas, por defecto que el usuario y la password sean iguales.

Cuando nos hayamos logado correctamente veremos que el navegador nos redirecciona a la URL que le hemos indicado en «service» y que nos muestra el contenido y el nombre del usuario que está logado.

Ahora en el mismo navegador (o en otro pestaña del mismo navegador) abrimos la URL: http://raguilera.com:8080/cas-example-2 y tendremos que ver que sin logarnos aparece el contenido con el nombre del usuario logado.

Podéis probar a hacerlo al revés, pero no sin antes eliminar la cache y las cookies del navegador.

7. Conclusiones

A mi este tipo de herramientas «satelites» me encantan, te permiten modularizar tu aplicación sin tener que cambiar ni una línea de código sólo a través de filtros o listener de Tomcat. En este caso esta herramienta nos resuelve el problema concreto de tener que implementar un SSO para todas nuestras aplicaciones, e incluso centralizar la seguridad tanto de aplicaciones web como de aplicaciones de escritorio. Ya os digo yo que los mayores problemas para seguir este tutorial los vais a encontrar a la hora de crear el certificado.

Cualquier duda o sugerencia en la zona de comentarios.

Saludos.

14 COMENTARIOS

  1. Hola,
    Estoy siguiendo el ejemplo descrito pero al levantar el tomcat me da un error, tengo la siguiente configuracion del server.xml

    Y el error al levantar el tomcat es

    19-07-2012 10:27:51 AM org.apache.catalina.core.StandardService start
    GRAVE: Failed to start connector [Connector[org.apache.coyote.Http11NioProtocol-
    8443]]
    LifecycleException: service.getName(): \\\»Catalina\\\»; Fall¾ el arranque del manej
    ador de protocolo: java.lang.NullPointerException
    at org.apache.catalina.connector.Connector.start(Connector.java:1129)
    at org.apache.catalina.core.StandardService.start(StandardService.java:5
    40)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754
    )
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
    19-07-2012 10:27:51 AM org.apache.coyote.ajp.AjpAprProtocol start

    ¿Alguna ayuda por fa? Estoy usando apache-tomcat-6.0.35 en Win 7 64bits

  2. Hola,

    Al validarme en la página del CAS, al redirigirme a la aplicación web sale el siguiente error:

    type Informe de Excepción

    mensaje javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found

    descripción El servidor encontró un error interno que hizo que no pudiera rellenar este requerimiento.

    excepción

    java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
    org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:341)
    org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:305)
    org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:50)
    org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:207)
    org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:169)
    org.jasig.cas.client.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:116)

    ¿Por qué puede generarse este error?

    Saludos y gracias,

    P.D.: Felicidades por la página.

  3. Muchas gracias Ruben,

    Necesito tu ayuda, estoy montando un CAS para un desarrollo que estoy haciendo.
    Despues de seguir tus pasos me sale esto en el browser:

    An error occurred during a connection to localhost:8080.

    SSL received a record that exceeded the maximum permissible length.

    (Error code: ssl_error_rx_record_too_long)

  4. Buenas, He montado un cas en suse que se valida contra un DA en windows 2008, permitiendo al usuario que está en el directorio activo acceder a la aplicacion, la duda que tengo es cuando hay un apache por delante del tomcat con otra url, cas no valida al usuario, hay alguna manera de poder hacerlo?
    Muchas Gracias.

    Un saludo

  5. Hola Ruben,

    He realizado el tutorial, no tengo errores, sin embargo cuando ingreso a la siguiente URL:

    http://localhost:8080/CasWebAppUno

    que es una de las dos aplicaciones web del ejemplo, efectivamente veo un cambio en la URL apuntando a :

    https://localhost:8443/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2FCasWebAppUno

    He indica lo siguiente:

    Firefox no puede establecer una conexión con el servidor en localhost:8443.

    Me puedes ayudar para determinar cual es el problema?.

    Muchas gracias.

    Saludos.

  6. Hola Caromeva,

    Ese error hace pensar que el puerto 8443 de tu Tomcat no está habilitado. Comprueba la configuración del server.xml y verifica que la línea referente al puerto SSL está habilitada.

    Espero haberte sido de ayuda.

    Saludos

  7. Buenas
    Saben a que se debe esta excepcion:
    &exception.message=Error+decoding+flow+execution.

    Estoy usando Jboss Wildfly 10

    Saludos.

  8. Hola! soy nueva en cas, en estos momentos hago mi tesis de grado en función de esto y necesito ayuda urgentemente! Bien, ya tengo Cas3.5.2 en tomcat7 (SO linux mint), una estructura de directorio con phpLDAPadmin, una aplicación en php y lo ultimo que hice fue instalar por consola phpCAS y la versión que está en los repositorios es la 1.3.2 (no tiene el example_simple.php). Tengo muchas dudas como ¿los archivos a incluir en la app son todos los que trajo la instalación de phpCAS? ¿que archivos debo modificar y cual es la modificacion exacta?. Tambien habia descargado php-cas1.3.4.tgz de https://developer.jasig.org/cas-clients/php/current/ (y este si trajo example_simple.php) ahora estoy confundida, o sea no se exactamente cuales son los archivos que deben incluirse en la aplicacion que se quiere proteger y tampoco se en que parte de la aplicacion se almacenan estos archivos. Necesito ayuda, necesito que funcione lo antes posible.

    Gracias!

  9. Buenas,
    Tengo el Wildfly 10 y me gustaria saber como tengo que configurar los pasos 4 y 5, ya que no tengo ni el fichero server.xml ni el web.xml

  10. Buenas tardes Rubén, tenemos una configuración muy útil del CAS integrando varias aplicaciones a través de servicios y quiero preguntarte si sabes como podemos adicionar otra que se integre a través de filtros dentro del mismo uso de SSO.

  11. Hola quisiera saber si me pueden ayudar con algo.
    Al abrir CAS no puedo ingresar con ninguna credencial de prueba, cual puedo utilizar para ingresar y logearme exitosamente?
    Gracias

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad