j'ai configuré Alfresco pour supporter l'authentification...

cancel
Showing results for 
Search instead for 
Did you mean: 
tegyat
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

Bonjour,
cette solution fonctionne avec alfresco 2.0, je n'ai pas vérifié pour 2.1
le code
package org.alfresco.web.app.servlet;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

import org.alfresco.config.ConfigService;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.AbstractAuthenticationFilter;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.NovellIChainsHTTPRequestAuthenticationFilter;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import edu.yale.its.tp.cas.client.filter.CASFilter;

public class CASAuthenticationFilter extends AbstractAuthenticationFilter
      implements Filter {

   private static final String LOCALE = "locale";

   public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";

   private static Log logger = LogFactory
         .getLog(CASAuthenticationFilter.class);

   private ServletContext context;

   private String loginPage;

   private AuthenticationComponent authComponent;

   private AuthenticationService authService;

   private TransactionService transactionService;

   private PersonService personService;

   private NodeService nodeService;

   private List<String> m_languages;

   public void init(FilterConfig config) throws ServletException {
      this.context = config.getServletContext();
      WebApplicationContext ctx = WebApplicationContextUtils
            .getRequiredWebApplicationContext(context);
      ServiceRegistry serviceRegistry = (ServiceRegistry) ctx
            .getBean(ServiceRegistry.SERVICE_REGISTRY);
      transactionService = serviceRegistry.getTransactionService();
      nodeService = serviceRegistry.getNodeService();

      authComponent = (AuthenticationComponent) ctx
            .getBean("authenticationComponent");
      authService = (AuthenticationService) ctx
            .getBean("authenticationService");
      personService = (PersonService) ctx.getBean("personService");

      // Get a list of the available locales

      ConfigService configServiceService = (ConfigService) ctx
            .getBean("webClientConfigService");
      LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService
            .getConfig("Languages").getConfigElement(
                  LanguagesConfigElement.CONFIG_ELEMENT_ID);

      m_languages = configElement.getLanguages();
   }

   public void doFilter(ServletRequest sreq, ServletResponse sresp,
         FilterChain chain) throws IOException, ServletException {
      // Get the HTTP request/response/session

      HttpServletRequest req = (HttpServletRequest) sreq;
      HttpServletResponse resp = (HttpServletResponse) sresp;

      HttpSession httpSess = req.getSession(true);

      // Check for the CAS user

      String authHdr = (String) req.getSession().getAttribute(CASFilter.CAS_FILTER_USER);
      if (logger.isDebugEnabled()) {
         if (authHdr == null) {
            logger.debug("CAS user not found.");
         } else {
            logger.debug("CAS user is <" + authHdr + ">");
         }
      }

      // Throw an error if we have an unknown authentication

      if ((authHdr == null) || (authHdr.length() < 1)) {
         resp.sendRedirect(req.getContextPath() + "/jsp/noaccess.jsp");
         return;
      }

      // Get the user

      String userName = authHdr;

      if (logger.isDebugEnabled()) {
         logger.debug("User = " + userName);
      }

      // See if there is a user in the session and test if it matches

      User user = (User) httpSess
            .getAttribute(AuthenticationHelper.AUTHENTICATION_USER);

      if (user != null) {
         try {
            // Debug

            if (logger.isDebugEnabled())
               logger.debug("User " + user.getUserName()
                     + " validate ticket");

            // Validate the user ticket

            if (user.getUserName().equals(userName)) {

               // Set the current locale
               authComponent.setCurrentUser(user.getUserName());
               I18NUtil.setLocale(Application.getLanguage(httpSess));
               chain.doFilter(sreq, sresp);
               return;
            } else {
               // No match
               setAuthenticatedUser(req, httpSess, userName);
            }
         } catch (AuthenticationException ex) {
            if (logger.isErrorEnabled())
               logger.error("Failed to validate user "
                     + user.getUserName(), ex);
         }
      }

      setAuthenticatedUser(req, httpSess, userName);

      // Redirect the login page as it is never seen as we always login by
      // name
      if (req.getRequestURI().endsWith(getLoginPage()) == true) {
         if (logger.isDebugEnabled())
            logger.debug("Login page requested, chaining …");

         resp.sendRedirect(req.getContextPath()
               + "/faces/jsp/browse/browse.jsp");
         return;
      } else {
         chain.doFilter(sreq, sresp);
         return;
      }

   }

   /**
    * Set the authenticated user.
    *
    * It does not check that the user exists at the moment.
    *
    * @param req
    * @param httpSess
    * @param userName
    */
   private void setAuthenticatedUser(HttpServletRequest req,
         HttpSession httpSess, String userName) {
      // Set the authentication
      authComponent.setCurrentUser(userName);

      // Set up the user information
      UserTransaction tx = transactionService.getUserTransaction();
      NodeRef homeSpaceRef = null;
      User user = null;
      try {
         tx.begin();
         user = new User(userName, authService.getCurrentTicket(),
               personService.getPerson(userName));
         homeSpaceRef = (NodeRef) nodeService.getProperty(personService
               .getPerson(userName), ContentModel.PROP_HOMEFOLDER);
         user.setHomeSpaceId(homeSpaceRef.getId());
         tx.commit();
      } catch (Throwable ex) {
         logger.error(ex);

         try {
            tx.rollback();
         } catch (Exception ex2) {
            logger.error("Failed to rollback transaction", ex2);
         }

         if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
         } else {
            throw new RuntimeException("Failed to set authenticated user",
                  ex);
         }
      }

      // Store the user

      httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
      System.out.println("User:" + user);
      System.out.println("Ticket:" + (user != null ? user.getTicket() : "–"));
      
      
      
      httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);

      // Set the current locale from the Accept-Lanaguage header if available

      Locale userLocale = parseAcceptLanguageHeader(req, m_languages);
      userLocale = new Locale("it", "IT");
      if (userLocale != null) {
         httpSess.setAttribute(LOCALE, userLocale);
         httpSess.removeAttribute(MESSAGE_BUNDLE);
      }

      // Set the locale using the session

      I18NUtil.setLocale(Application.getLanguage(httpSess));
      
      System.out.println("Setting " + Application.getLanguage(httpSess) + " locale");
   }

   public void destroy() {

   }

   /**
    * Return the login page address
    *
    * @return String
    */
   private String getLoginPage() {
      if (loginPage == null) {
         loginPage = Application.getLoginPage(context);
      }

      return loginPage;
   }

}
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

J'ai compilé (avec Eclipse) et suivit les instructions, lorsque je me rends sur la page de login, je ne suis pas redirigé vers CAS mais le message "You have no access to Alfresco" m'est affiché. Rien ne s'ajoute dans les logs.
Avez-vous eu le même problème ?

Note : je n'ai encore fait aucune configuration des utilisateurs.
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

J'ai placé les blocs xml vers le début du fichier web.xml. Maintenant je suis bien redirigé vers CAS mais lorsque je retourne sur Alfresco, il est affiché :

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
caused by:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
caused by:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

J'ai pourtant généré un certificat avec keytool, en spécifiant le bon nom de domaine …
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

Ok, tout semble fonctionner correctement à présent : j'ai exporté le certificat du keystore et je l'ai importer dans le keystore du JDK.
Par contre je suis toujours connecté en guest lorsque je passe par CAS. Est-ce normal ? Est-ce qu'il y a moyen de se conncecter à un utilisateur dans Alfresco (ayant le même login que celui spécifié dans CAS) ?

Par la suite, j'ai supprimé le guest et après m'être identifé à CAS, je suis redirigé vers le formulaire d'identification Alfresco …

Merci
lme
Partner

Re: j'ai configuré Alfresco pour supporter l'authentification...

Le but de CAS est bien de retrouver ton utilisateur authentifié par CAS automatiquement dans Alfresco (et éviter l'authentification d'Alfresco).
D'après ce que tu dis, il semblerait que tu n'aies pas modifier correctement ton fichier web.xml. Quelles modifications as-tu effectuées dans ce fichier ?
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

J'ai rajouté les blocs suivants juste après la déclaration du doctype dans le fichier alfresco/WEB-INF/web.xml :

 
<filter>
       <filter-name>CAS Required</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://<nom_de_mon_serveur_cas>:8443/cas/login</param-value>
       </init-param>
       <init-param>
           <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
           <param-value>https://<nom_de_mon_serveur_cas>:8443/cas/serviceValidate</param-value>
       </init-param>
   
       <init-param>
           <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
           <param-value><nom_de_mon_serveur_cas>:8443</param-value>
       </init-param>
</filter>

<filter-mapping>
      <filter-name>CAS Required</filter-name>
      <url-pattern>/faces/*</url-pattern>
      </filter-mapping>
      <filter-mapping>
           <filter-name>CAS Required</filter-name>
           <url-pattern>/template/*</url-pattern>
     </filter-mapping>
     <filter-mapping>
           <filter-name>CAS Required</filter-name>
           <url-pattern>/download/*</url-pattern>
   </filter-mapping>

<filter>
      <filter-name>Authentication Filter</filter-name>
      <filter-class>org.alfresco.web.app.servlet.CASAuthenticationFilter</filter-class>
</filter>
lme
Partner

Re: j'ai configuré Alfresco pour supporter l'authentification...

Il me semble que tu dois chaîner les 2 filtres de cette manière (en respectant l'ordre) :

<filter-mapping> 
      <filter-name>CAS Required</filter-name>
      <url-pattern>/faces/*</url-pattern>
</filter-mapping>
<filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/faces/*</url-pattern>
</filter-mapping>
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

Voici le nouveau contenu de mon web.xml. Je l'ai modifié comme tu me l'as indiqué mais ça rien n'a changé : j'ai crée un utilisateur dans Alresco portant le même login / pwd qu'un utilisateur pouvant s'identifier dans CAS et lorsque je je m'identifie avec succès dans CAS je suis redirigé vers le formulaire de login d'Alfresco.

<filter> 
    <filter-name>CAS Required</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://<mon_serveur_cas>:8443/cas/login</param-value>
    </init-param>
    <init-param>
        <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
        <param-value>https://<mon_serveur_cas>:8443/cas/serviceValidate</param-value>
    </init-param>
     <init-param>
        <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
        <param-value><mon_serveur_cas>:8443</param-value>
    </init-param>
</filter>

<filter>
   <filter-name>Authentication Filter</filter-name>
   <filter-class>org.alfresco.web.app.servlet.CASAuthenticationFilter</filter-class>
</filter>

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

<filter-mapping>
     <filter-name>CAS Required</filter-name>
     <url-pattern>/template/*</url-pattern>
</filter-mapping>
<filter-mapping>
     <filter-name>CAS Required</filter-name>
     <url-pattern>/download/*</url-pattern>
</filter-mapping>
lme
Partner

Re: j'ai configuré Alfresco pour supporter l'authentification...

Voici mon fichier web.xml :

   <filter>
      <filter-name>Authentication 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://serveur_cas:8443/cas/login</param-value>
      </init-param>
      <init-param>
          <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
          <param-value>https://serveur_cas:8443/cas/serviceValidate</param-value>
      </init-param>
      <init-param>
          <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
          <param-value>serveur_cas:8080</param-value>
      </init-param>
   </filter>

   <filter>
      <filter-name>CAS Authentication</filter-name>
      <filter-class>org.alfresco.web.app.servlet.CasAuthenticationFilter</filter-class>
   </filter>

   <filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/faces/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
      <filter-name>CAS Authentication</filter-name>
      <url-pattern>/faces/*</url-pattern>
   </filter-mapping>
  
   <filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/navigate/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
      <filter-name>CAS Authentication</filter-name>
      <url-pattern>/navigate/*</url-pattern>
   </filter-mapping>
  
   <filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/command/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
      <filter-name>CAS Authentication</filter-name>
      <url-pattern>/command/*</url-pattern>
   </filter-mapping>
  
   <filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/template/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
      <filter-name>CAS Authentication</filter-name>
      <url-pattern>/template/*</url-pattern>
   </filter-mapping>
  
   <filter-mapping>
      <filter-name>Authentication Filter</filter-name>
      <url-pattern>/download/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
      <filter-name>CAS Authentication</filter-name>
      <url-pattern>/download/*</url-pattern>
   </filter-mapping>
Quelques questions :
- quand tu arrives sur la page http://serveur_alfresco:8080/alfresco/, es-tu bien redirigé vers la page de login CAS ?
- et une fois l'authentification réussi dans CAS, vers quelle page es-tu redirigée (faire attention au http/https et au port !) ?
- quel est le backend de CAS ?
- quelque chose d'intéressant dans les logs (CAS ou Alfresco) ?
pierrick
Member II

Re: j'ai configuré Alfresco pour supporter l'authentification...

Je test ton web.xml tout de suite. En attendant, voici les réponses à tes questions :


- quand tu arrives sur la page http://serveur_alfresco:8080/alfresco/, es-tu bien redirigé vers la page de login CAS ?
Oui. Remarque : Alfresco et CAS sont sur le même Tomcat et je n'utilise qu'un seul connecteur. Par conséquent l'url d'accès à Alfresco est https://serveur_alfresco:8443/alfresco/
- et une fois l'authentification réussi dans CAS, vers quelle page es-tu redirigée (faire attention au http/https et au port !) ?
La page de login : https://serveur_alfresco:8443/alfresco/faces/jsp/login.jsp
- quel est le backend de CAS ?
Active Directory
- quelque chose d'intéressant dans les logs (CAS ou Alfresco) ?
Rien seulement des exceptions CAS liées au module SPNEGO (pour une utilisation avec NTLM)