Configuración de Alfresco Community 3.2 con CAS

alfresco-dashboardTenemos Alfresco y Liferay autenticando con LDAP. Vamos a ir un paso más buscando el Single Sign On -SSO-. Para ello vamos a utilizar el «Central Authentication System».
Sitio web: Jasig CAS
Información sobre la instalación en: Alfresco Wiki

Prerrequisitos

  • Servidor CAS instalado
  • Certificado SSL para el servidor CAS instalado

Pasos

 Paso 1. Importación del certificado de servidor en el almacén de confianza -cacerts- de la JRE que utilice el servidor de Alfresco

Como vimos en el post de configuración de Tomcat para SSL, tenemos que instalar el certificado en la lista de confianza de la JRE. Esto sólo es necesario si nuestro certificado es self-signed; es decir es un certificado generado por nosotros y no está respaldado por ninguna autoridad certificadora

Por cualquiera de los dos métodos ya vistos instalamos el certificado en la JRE de Alfresco

Método I: importación con keytool

C:\desarrollo\java\install\jdk1.6.0_14\bin>keytool -import -file server.crt -alias tomcat_cas -keypass clave_almacen -keystore ..\jre\lib\security\cacerts

NOTA: Obviamente la ruta a cacerts debe ser la de la JRE que utilice el servidor de Alfresco

Método II: utilidad Installcert

En este caso tenéis que comprobar que la variable JAVA_HOME apunte a la raíz de la JRE en la que queréis instalar el certificado. Echad un vistazo al código fuente de Installcert si tenéis dudas.
Código fuente de InstallCert

C:\desarrollo>java -cp . InstallCert gammu:8444

Paso 2. Interceptar las peticiones a páginas JSF con el filtro de CAS

Queremos que las peticiones al front-end web pasen previamente por CAS, con objeto de que éste sea el encargado de la autenticación. Para ello vamos a definir un filtro que va a aplicarse sobre el patrón URL /faces/*

Paso 2.1. Configuración de Tomcat

Debemos añadir el cliente de CAS al Common Class Loader de Tomcat. En nuestro caso copiaremos el cliente casclient-2.1.1.jar en el directorio C:\desarrollo\java\install\alfresco-3.2\tomcat\lib
NOTA:
Más información sobre los classloader de Tomcat en: http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

El cliente de CAS lo podemos obtener en: http://www.jasig.org/cas/client-integration/java-client

Es probable que observéis una excepción en los log de Tomcat. Éste ha sido mi caso y la razón es que el cliente de CAS tenía una dependencia con Commons Logging. He añadido el JAR commons-logging-1.1.1.jar al mismo directorio del Common Class Loader y ha funcionado. No obstante siempre que añadamos JARs hay que analizar si realmente es necesario.

Commons Logging podemos obtenerlo de: http://commons.apache.org/logging/

Paso 2.2. Definir el filtro en web.xml

Una vez copiado el cliente de CAS vamos a definir el filtro Http que hará que las peticiones autentiquen con CAS. Para esto vamos a modificar el descriptor de la aplicación web de Alfresco C:\desarrollo\java\install\alfresco-3.2\tomcat\webapps\alfresco\WEB-INF\web.xml

NOTA: Recomiendo validar el archivo XML una vez hechas las modificaciones o realizar estas desde un entorno como Eclipse.

Definimos el filtro. Lo ubicamos justo después del último filter definido o antes del primero o en medio. A diferencia de los mapping da igual dónde lo pongamos.

<!– FER_BEGIN cas client filter –>
 <filter>
  <filter-name>CAS Filter</filter-name>
  <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>
  <init-param>
   <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
   <param-value>https://gammu:8444/cas-server-webapp-3.3.3/login</param-value&gt;
  </init-param>
  <init-param>
   <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
   <param-value>https://gammu:8444/cas-server-webapp-3.3.3/serviceValidate</param-value&gt;
  </init-param>
  <init-param>
   <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
   <param-value>gammu:9090</param-value>
  </init-param>
 </filter>

 <!–  FER_END –>
 <!– cas client filter –>

En mi caso GAMMU es el nombre de mi máquina y las URL son las de mi servidor CAS -versión 3.3.3-. Os recomiendo que hagáis unas pruebas con CAS para ver si las URLs de Login y validate son las mismas.
En el nombre de servidor indico también el puerto donde tengo escuchando Alfresco.

Una vez declarado el filtro tenemos que indicar el mapping; es decir, sobre qué URLs o Servlets va a trabajar este filtro. En este caso sí que es importante dónde se coloca el filtro, dado que podemos tener varios filtros mapeados sobre una misma URL.
Es interesante consultar este post: http://www.coderanch.com/t/173700/Web-Component-Certification-SCWCD/certification/order-filter-mapping

En mi caso voy a colocar mi mapping justo antes del definido para Authentication Filter

<filter-mapping>
     <filter-name>CAS Filter</filter-name>
     <url-pattern>/faces/*</url-pattern>
 </filter-mapping>
 <!– end of cas client filter –>

Paso 3. Modificación del filtro de autenticación de la aplicación web de Alfresco

jasig-CASSi ahora probamos Alfresco. En mi caso una petición a http://gammu:9090/alfresco , veremos cómo nos aparece la pantalla de login de CAS.
El problema es que una vez autenticados sí se nos redirige a Alfresco, pero vemos que entramos como invitado; es decir: ¿para qué ha valido lo de CAS?

Sí ha valido, lo que pasa es que también tenemos que modificar el filtro de autenticación que utiliza Alfresco para peticiones al front-end web. Tenemos que instruir a Alfresco sobre dónde obtener los datos del usuario autenticado.
Alfresco define varios filtros para distintas URLs y métodos de acceso. En concreto vamos a modificar el filtro que se aplica para las peticiones del front-end web. Dado que Alfresco construye la vista con Java Server Faces -JSF- el filtro deberá interceptar las peticiones a URLs que contengan faces

 <filter>
  <filter-name>Authentication Filter</filter-name>
  <description>Authentication filter mapped only to faces URLs. Other
   URLs generally use proprietary means to talk to the
   AuthenticationComponent</description>  
  <!– FER_BEGIN
  <filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>
  <init-param>
   <param-name>beanName</param-name>
   <param-value>AuthenticationFilter</param-value>
  </init-param>
  FER_END –>
  
  <filter-class>com.keembay.alfresco.web.app.servlet.CASAuthenticationFilter</filter-class>
  <init-param>
   <param-name>cas.user.label</param-name>
   <param-value>edu.yale.its.tp.cas.client.filter.user</param-value>
  </init-param>

 </filter>

En verde indico que he comentado la clase que inicialmente implementaba el filtro. La nueva clase es com.keembay.alfresco.web.app.servlet.CASAuthenticationFilter
NOTA:
¿Dónde obtenerla?: http://keembay.com/alfresco/extras/keembay-alfresco-cas.jar

El mapping que estaba previamente definido no hay que tocarlo:

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

Lo único que tenemos que fijarnos en el orden en el que se ejecutan los filtros. Dado que la nueva clase precisa de atributos que establece el CAS Filter, debemos tener cuidado sobre cómo colocamos los <filter-mapping>. En mi caso siempre tengo el mapping de CAS antes que el del Authentication Filter.

Paso 3. Logout

Si no he metido la pata con la explicación, Alfresco debería funcionar más o menos con CAS. No obstante podéis experimentar un problema a la hora de hacer logout: hacéis logout pero seguís autenticados… ¿por qué?

Si os fijáis en la definición del filtro de CAS no hay una URL de logout. Realmente sí existe pero el filtro no la contempla.

Una solución no muy elegante es modificar la página relogin.jsp. Modifcamos C:\desarrollo\java\install\alfresco-3.2\tomcat\webapps\alfresco\jsp\relogin.jsp

<%@ page import=»org.alfresco.web.app.servlet.AuthenticationHelper» %>
<%@ page import=»javax.servlet.http.Cookie» %>
<%@ page buffer=»16kb» contentType=»text/html;charset=UTF-8″ %>
<%@ page isELIgnored=»false» %>
<%
// logout CAS
response.sendRedirect(«
https://gammu:8444/cas-server-webapp-3.3.3/logout«);

// remove the username cookie value if explicit logout was requested by the user
if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) != null)
{

Este último punto habrá que estudiarlo más a fondo, porque es bastante ñapa -una más para el ñapositorio-.

7 comentarios

  1. Hola Fer,
    He encontrado este blog, buscando los prerrequisitos de instalación de Alfresco.
    Estamos preparando un proyecto para una asociación de vecinos en Valencia, y vamos en el paso de seleccionar una herramienta de gestion documental, tenemos información de nuxeo y otros, pero de Alfresco sólo tenemos lo que vale la consultoría…. Sabes donde puedo encontrar información y comparativas sobre requisitos de instalación y funcionalidad de Alfresco con otros gestores documentales, preferiblemente Open.
    Gracias…. Y muy detallada y buena la información de configuración.
    Un saludo

  2. Hola Claudia

    Perdona que no te haya respondido, últimamente tengo abandonado el blog (como fácilmente se puede ver) porque tengo bastante lío con el trabajo.

    Respecto a comparativas no recuerdo ahora ningún sitio concreto, sí que es verdad que buscando por Google hacían una comparación entre Alfresco y Nuxeo, estaba bastante bien.

    Respecto a documentación de Alfresco yo tengo algunos manuales del Wiki (el de instalación sobre todo) y algunos libros editados por la editorial Packt Publishing.

    Respecto a otros productos te diría los típicos (que ya habrás mirado): Liferay, Open CMS, Joomla, Sharepoint (windows)

    Siento no poder clarificarte mucho el tema.

    Un saludo

  3. Buenas,

    He seguido estas instrucciones (muy útiles) y accedo a Alfresco correctamente mediante CAS. En mi caso, CAS autentica contra un LDAP (CentOS-DS para mas señas)

    Ademas he tengo CAS integrado con otras aplicaciones (Moodle, dotProject, GLPI…).

    El problema es que necesito dar de alta en Alfresco los usuarios que ya existen en LDAP para poder hacer login. Esto no me ocurre con las otras aplicaciones, que, en algunos casos, incluso consulta directamente LDAP para obtener los atributos de los usuarios que dan de alta automaticamente.

    ¿Sabes si hay posibilidad de hacer esto que quiero? Te agradecería cualquier tipo de pista, referencia, documentacion…

    Gracias de antemano y enhorabuena por el blog.

    • Hola Rai

      No he podido probar la sincronización dado que como puedes ver por las fechas de los post he tenido que dejar aparcado el tema (espero retomarlo en vacaciones). Lo único que te puedo indicar es que mires en esta URL

      http://wiki.alfresco.com/wiki/Alfresco_Authentication_Subsystems#Example_2:_Advanced_LDAP_Chain

      Seguramente ya habrás echado un ojo, pero por si acaso…

      Un par de libros que suelo utilizar:
      Alfresco Developer Guide de Jeff Pots. Ed. Packt Publishing
      Alfresco 3 Enterprise Content Management Implementation de Munwar Shariff. Ed. Packt Publishing

      Espero que esto te pueda valer para algo.

      Un saludo !

      • De acuerdo, le echaré un vistazo con mayor profundidad al artículo porque, aunque lo conocía, solo lo había leído de pasada. Los libros no sabía ni que existiesen 🙂

        Si consigo hacer que funcione, lo postearé por aquí por si es de utilidad.

        Felices Fiestas y muchas gracias!!!

      • Me interesa saber como ha ido la integración con LDAP de Alfresco.

        ¿Has solucionado el problema de tener que dar de alta los usuarios del LDAP en alfresco para que te autentique en éste de forma correcta? y si lo has solucionado, ¿con que permisos accede ese usuario del LDAP que no está dado de alta en ALFRESCO?

        Un saludo, espero que me respondas por que me trae esto un poco de cabeza.

  4. Qué tal Fer? Fenomeno el post, pero oye una cosina, ¿no tuviste que tocar la cadena de autenticación en el alfresco-global.properties:

    authentication.chain=external1:external

    ¿Tuviste que dar de alta ese subsistema? ¿Y el sysAdmin?

    Gracias tron!!!

Replica a Claudia Rebeca Valderrama Cancelar la respuesta