cancel
Showing results for 
Search instead for 
Did you mean: 

Alfresco integration with CAS with Acegi

escaglia
Champ in-the-making
Champ in-the-making
Hello everybody,
we'd like to submit you the way we integrated Alfresco with our CAS, asking you for help on (at least) a couple of doubts we have.
The relevant part of web.xml we used is:


<filter>
          <filter-name>Acegi CAS Processing Filter</filter-name>
          <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
          <init-param>
            <param-name>targetClass</param-name>
           <param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value>
          </init-param>
</filter>
       <filter-mapping>
          <filter-name>Acegi CAS Processing Filter</filter-name>
          <url-pattern>/*</url-pattern>
</filter-mapping>

The file authentication-services-context.xml we used is:


<beans>
    <!–                                                                    –>
    <!– The Acegi authentication manager.                                  –>
    <!–                                                                    –>
    <!– Provders are asked to authenticate in order.                       –>
    <!– First, is a provider that checks if an acegi authentication object –>
    <!– is already bound to the executing thread. If it is, and it is set  –>
    <!– as authenticated then no further authentication is required. If    –>
    <!– this is absent, Acegi validates the password for every method      –>
    <!– invocation, which is too CPU expensive. If we set an               –>
    <!– authentication based on a ticket etc …. or we want to set the    –>
    <!– the system user as the current user … we do not have the         –>
    <!– password. So if we have set an authentication and set it as        –>
    <!– authenticated that is sufficient to validate the user.             –>
    <!–                                                                    –>
    <!– If the authentication bound to the current thread is not set as    –>
    <!– authenticated the standard Acegi DAO Authentication provider       –>
    <!– is used to authenticate.                                           –>
    <!–                                                                    –>

   <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
         <value>
          CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          PATTERN_TYPE_APACHE_ANT
            /faces/**=Cas2AlfrescoContextIntegrationFilter,securityEnforcementFilter
            /j_acegi_cas_security_check**=Cas2AlfrescoContextIntegrationFilter,casProcessingFilter
         </value>
      </property>
    </bean>

    <bean id="Cas2AlfrescoContextIntegrationFilter" class="org.alfresco.web.app.servlet.Cas2AlfrescoContextIntegrationFilter">
       <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property>
    </bean>








    <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="authenticatedAuthenticationPassthroughProvider" />
                <ref bean="casAuthenticationProvider" />
            </list>
        </property>
    </bean>

   <bean id="serviceProperties" class="net.sf.acegisecurity.ui.cas.ServiceProperties">
     <property name="service"><value>http://pc29029.csi.it:8080/alfresco/j_acegi_cas_security_check</value></property>
     <property name="sendRenew"><value>false</value></property>
   </bean>
   <bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter">
     <property name="authenticationManager"><ref bean="authenticationManager"/></property>
     <property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
     <property name="defaultTargetUrl"><value>/</value></property>
     <property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
   </bean>
   <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
        <property name="authenticationEntryPoint"><ref bean="casProcessingFilterEntryPoint"/></property>
      <property name="filterSecurityInterceptor" ref="filterInvocationInterceptor"/>
    </bean>

   <bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager"><ref bean="authenticationManager"/></property>
        <property name="accessDecisionManager"><ref bean="httpRequestAccessDecisionManager"/></property><!–<ref bean="accessDecisionManager"/></property–>
        <property name="objectDefinitionSource">
            <value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=ROLE_AUTHENTICATED
            </value>
        </property>
    </bean>
   <bean id="httpRequestAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
      <property name="allowIfAllAbstainDecisions"><value>false</value></property>
      <property name="decisionVoters">
         <list><ref bean="roleVoter"/></list>
      </property>
   </bean>
    <!– ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ –>
    <!– An access decision voter that reads ROLE_* configuaration settings –>
    <!– <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> –>
    <!– <bean id="ACLEntryVoter" class="org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoter"/> –>
    <!– An access decision manager used by the business objects –>
   
   <bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
     <property name="loginUrl"><value>https://cstvip01.csi.it/ssobart/login</value></property>
     <property name="serviceProperties"><ref bean="serviceProperties"/></property>
   </bean>

   <bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider">
     <property name="casAuthoritiesPopulator"><ref bean="casAuthoritiesPopulator"/></property>
     <property name="casProxyDecider"><ref bean="casProxyDecider"/></property>
     <property name="ticketValidator"><ref bean="casProxyTicketValidator"/></property>
     <property name="statelessTicketCache"><ref bean="statelessTicketCache"/></property>
     <property name="key"><value>my_password_for_this_auth_provider_only</value></property>
   </bean>
   
   <bean id="casProxyTicketValidator" class="net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
     <property name="casValidate"><value>http://alessandria.cst-alessandria.csi.it/ssobart/serviceValidate</value></property>
     <property name="proxyCallbackUrl"><value>https://localhost:8443/contacts-cas/casProxy/receptor</value></property>
     <property name="serviceProperties"><ref bean="serviceProperties"/></property>
     <!– <property name="trustStore"><value>/some/path/to/your/lib/security/cacerts</value></property> –>
   </bean>
   
   <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
     <property name="configLocation">
       <value>classpath:/ehcache-failsafe.xml</value>
     </property>
   </bean>
      
   <bean id="ticketCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
     <property name="cacheManager">
       <ref local="cacheManager"/>
     </property>
     <property name="cacheName">
       <value>ticketCache</value>
     </property>
   </bean>
     
   <bean id="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache">
     <property name="cache"><ref local="ticketCacheBackend"/></property>
   </bean>
   
   <bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
     <property name="authenticationDao"><ref bean="alfDaoImpl"/></property>
   </bean>
   
   <bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets"/>

    <bean id="inMemoryDaoImpl" class="org.alfresco.repo.security.authentication.InMemoryDaoImpl">
        <property name="userMap">
            <value>
               AAAAAA00B77B000F=***,ROLE_ADMIN
                admin=***,ROLE_ADMIN
                    gcs=***,ROLE_ADMIN
                mc=***,ROLE_ADMIN,ROLE_TELLER,ROLE_SUPERVISOR
                    peter=***,disabled,ROLE_TELLER
            </value>
        </property>
    </bean>

    <!– We provide a DAO to plug into the Acegi DaoAuthenticationProvider  –>

    <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="authenticationDao">
            <ref bean="authenticationDao" />
        </property>
        <property name="saltSource">
            <ref bean="saltSource" />
        </property>
        <property name="passwordEncoder">
            <ref bean="passwordEncoder" />
        </property>
    </bean>

    <!– An authentication Provider that just believes authentications      –>
    <!– bound to the local thread are valid if they are set as             –>
    <!– authenticated.                                                     –>

    <bean id="authenticatedAuthenticationPassthroughProvider" class="org.alfresco.repo.security.authentication.AuthenticatedAuthenticationPassthroughProvider" />

    <!– The authroity DAO implements an interface extended from the Acegi  –>
    <!– DAO that supports CRUD.                                            –>

    <bean id="alfDaoImpl" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyInterfaces">
            <value>org.alfresco.repo.security.authentication.MutableAuthenticationDao</value>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager" />
        </property>
        <property name="target">
            <ref bean="authenticationDao"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">${server.transaction.mode.default}</prop>
            </props>
        </property>
    </bean>
   
    <bean id="authenticationDao" class="org.alfresco.repo.security.authentication.RepositoryAuthenticationDao">
       <property name="nodeService">
           <ref bean="nodeService" />
       </property>
       <property name="dictionaryService">
           <ref bean="dictionaryService" />
       </property>
       <property name="namespaceService">
           <ref bean="namespaceService" />
       </property>
       <property name="searchService">
           <ref bean="searchService" />
       </property>
       <property name="userNamesAreCaseSensitive">
          <value>${user.name.caseSensitive}</value>
       </property>
       <property name="passwordEncoder">
           <ref bean="passwordEncoder" />
       </property>
    </bean>

    <!– The DAO also acts as a salt provider.                              –>
   
    <alias alias="saltSource" name="alfDaoImpl"/>

    <!– Passwords are encoded using MD4                                    –>
    <!– This is not ideal and only done to be compatible with NTLM         –>
    <!– authentication against the default authentication mechanism.       –>

    <bean id="passwordEncoder" class="org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl"></bean>


    <!– A transactional wrapper around the implementation.                 –>
    <!– TODO: This should be removed.                                      –>             

    <bean id="authenticationService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyInterfaces">
            <value>org.alfresco.service.cmr.security.AuthenticationService</value>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager" />
        </property>
        <property name="target">
            <ref bean="authenticationServiceImpl" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">${server.transaction.mode.default}</prop>
            </props>
        </property>
    </bean>

    <!– The Authentication Service implementation.                         –>
    <!–                                                                    –>
    <!– This delegates its work to two services:                           –>
    <!– an AuthenticationComponent and a MutableAuthenticationDAO.         –>
    <!–                                                                    –>
    <!– The permissions service is required so that permissions can be     –>
    <!– cleaned up when a user is deleted.                                 –>
   
    <bean id="authenticationServiceImpl" class="org.alfresco.repo.security.authentication.AuthenticationServiceImpl">
        <property name="authenticationDao">
            <ref bean="authenticationDao" />
        </property>
        <property name="ticketComponent">
            <ref bean="ticketComponent" />
        </property>
        <property name="authenticationComponent">
            <ref bean="authenticationComponentImpl" />
        </property>
    </bean>

    <!– A transactional wrapper that should be removed.                    –>

    <bean id="authenticationComponent" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyInterfaces">
            <value>org.alfresco.repo.security.authentication.AuthenticationComponent</value>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager" />
        </property>
        <property name="target">
            <ref bean="authenticationComponentImpl" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">${server.transaction.mode.default}</prop>
            </props>
        </property>
    </bean>

    <!– The authentication component.                                      –>

    <bean id="authenticationComponentImpl" class="org.alfresco.repo.security.authentication.AuthenticationComponentImpl">
        <property name="authenticationDao">
            <ref bean="authenticationDao" />
        </property>
        <property name="authenticationManager">
            <ref bean="authenticationManager" />
        </property>
        <property name="allowGuestLogin">
            <value>true</value>
        </property>
    </bean>

   
    <!– Simple Authentication component that rejects all authentication requests –>
    <!– Use this defintion for Novell IChain integration.                        –>
    <!– It should never go to the login screen  so this is not required          –>
    <!– (Enterprise version only)                                                –>
   
    <!–
    <bean id="authenticationComponentImpl" class="org.alfresco.repo.security.authentication.SimpleAcceptOrRejectAllAuthenticationComponentImpl">
    </bean>
    –>



    <!– The person service.                                                –>

    <bean id="personService" class="org.alfresco.repo.security.person.PersonServiceImpl">
      <property name="nodeService">
          <ref bean="nodeService" />
      </property>
      <property name="searchService">
          <ref bean="searchService" />
      </property>
      <property name="permissionServiceSPI">
         <ref bean="permissionServiceImpl" />
      </property>
        <property name="authorityService">
           <ref bean="authorityService" />
        </property>
      <property name="namespacePrefixResolver">
         <ref bean="namespaceService" />
      </property>
        <!– Configurable properties.                                 –>
        <!–                                                          –>
        <!– TODO:                                                    –>
        <!– Add support for creating real home spaces adn setting    –>
        <!– permissions on the hame space and people created.        –>
        <!–                                                          –>
        <!– The store in which people are persisted.                 –>
        <property name="storeUrl">
           <value>${spaces.store}</value>
        </property>
        <!– The path to the company home space, used to set the      –>
        <!– default home space for users that are created if         –>
        <!– missing.                                                 –>
        <property name="companyHomePath">
           <value>/${spaces.company_home.childname}</value>
        </property>
        <!– Some authentication mechanisms may need to create people –>
        <!– in the repository on demand. This enables that feature.  –>
        <!– If dsiabled an error will be generated for missing       –>
        <!– people. If enabled then a person will be created and     –>
        <!– persisted.                                               –>
        <!–                                                          –>
        <!– This value should be false or only true if the           –>
        <!– repository is mutable; set from the property             –>
        <!– ${server.transaction.allow-writes}                       –>
        <property name="createMissingPeople">
           <value>${server.transaction.allow-writes}</value>
        </property>
        <!– Set is user names are case sensitive - taken from the    –>
        <!– repository wide setting - you are advised not to change  –>
        <!– this setting.                                            –>
        <!– This value should be ${user.name.caseSensitive}          –>
        <property name="userNamesAreCaseSensitive">
           <value>${user.name.caseSensitive}</value>
        </property>
    </bean>

    <!– The ticket component.                                              –>
    <!– Used for reauthentication                                          –>
    <bean id="ticketComponent" class="org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl">
        <!– The period for which tickets are valid in XML duration format. –>
        <!– The default is P1H for one hour.                               –>
        <property name="validDuration">
            <value>P1H</value>
        </property>
        <!– Do tickets expire or live for ever?                            –>
        <property name="ticketsExpire">
            <value>false</value>
        </property>
        <!– Are tickets only valid for a single use?                       –>
        <property name="oneOff">
            <value>false</value>
        </property>
    </bean>
   
</beans>


We used the class FilterToBeanProxy to make spring load the class FilterChainProxy which can apply a filter chain.

We used the filter Cas2AlfrescoContextIntegrationFilter which extends from net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter to put into session the object ACEGI_SECURITY_CONTEXT and the ticket _alfAuthTicket.
ACEGI_SECURITY_CONTEXT is a SecureContextImpl containing as a property CasAuthenticationToken, result of the Cas authentication process. _alfAuthTicket instead contains org.alfresco.web.bean.repository.User, object required by Alfresco after authentication.

We didn't use InMemoryDaoImpl but we used Alfresco alfDaoImpl bean as the Alfresco user store. This means that a user, beside existing in the Cas repository, must be priorly created by an admin user in Alfresco.
First question: is there a way to force user creation at first login?

Here is the code of our class:
Cas2AlfrescoContextIntegrationFilter

package org.alfresco.web.app.servlet;



import net.sf.acegisecurity.context.Context;

import net.sf.acegisecurity.context.ContextHolder;

import net.sf.acegisecurity.context.security.SecureContextImpl;



import org.alfresco.model.ContentModel;

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.bean.repository.User;

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 java.io.IOException;



import javax.servlet.FilterChain;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.transaction.UserTransaction;





public class Cas2AlfrescoContextIntegrationFilter extends net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter {

    //~ Static fields/initializers =============================================



    protected static final Log logger = LogFactory.getLog(Cas2AlfrescoContextIntegrationFilter.class);

    private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";

    public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";

    public static final String ALF_SECURITY_CONTEXT_KEY = "_alfAuthTicket";



    //~ Instance fields ========================================================



    private Object contextObject;



    /**

     * Indicates if this filter can create a HttpSession if needed

     * (sessions are always created sparingly, but setting this value to false

     * will prohibit sessions from ever being created). Defaults to true.

     */

    private boolean allowSessionCreation = true;



    //~ Methods ================================================================



    public void doFilter(ServletRequest request, ServletResponse response,

        FilterChain chain) throws IOException, ServletException {

        if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {

            // ensure that filter is only applied once per request

            chain.doFilter(request, response);

        } else {

            if (request != null) {

                request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

            }



            if (ContextHolder.getContext() != null) {

                if (logger.isWarnEnabled()) {

                    logger.warn(

                        "ContextHolder should have been null but contained: '"

                        + ContextHolder.getContext() + "'; setting to null now");

                }



                ContextHolder.setContext(null);

            }



            HttpSession httpSession = null;

            boolean httpSessionExistedAtStartOfRequest = false;



            try {

                httpSession = ((HttpServletRequest) request).getSession(false);

            } catch (IllegalStateException ignored) {}



            if (httpSession != null) {

                httpSessionExistedAtStartOfRequest = true;



                Object contextObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY);



                if (contextObject != null) {

                    if (contextObject instanceof Context) {

                        if (logger.isDebugEnabled()) {

                            logger.debug(

                                "Obtained from ACEGI_SECURITY_CONTEXT a valid Context and set to ContextHolder: '"

                                + contextObject + "'");

                        }



                        ContextHolder.setContext((Context) contextObject);

                    } else {

                        if (logger.isWarnEnabled()) {

                            logger.warn(

                                "ACEGI_SECURITY_CONTEXT did not contain a Context but contained: '"

                                + contextObject

                                + "'; are you improperly modifying the HttpSession directly (you should always use ContextHolder) or using the HttpSession attribute reserved for this class?");

                        }

                    }

                } else {

                    if (logger.isDebugEnabled()) {

                        logger.debug(

                            "HttpSession returned null object for ACEGI_SECURITY_CONTEXT");

                    }

                }

            } else {

                if (logger.isDebugEnabled()) {

                    logger.debug("No HttpSession currently exists");

                }

            }



            if (ContextHolder.getContext() == null) {

                ContextHolder.setContext(generateNewContext());



                if (logger.isDebugEnabled()) {

                    logger.debug(

                        "As ContextHolder null, setup ContextHolder with a fresh new instance: '"

                        + ContextHolder.getContext() + "'");

                }

            }



            // Make the HttpSession null, as we want to ensure we don't keep

            // a reference to the HttpSession laying around in case the

            // chain.doFilter() invalidates it.

            httpSession = null;



            // Proceed with chain

            chain.doFilter(request, response);



            // Store context back to HttpSession

            try {

                httpSession = ((HttpServletRequest) request).getSession(false);

            } catch (IllegalStateException ignored) {}



            if ((httpSession == null) && httpSessionExistedAtStartOfRequest) {

                if (logger.isDebugEnabled()) {

                    logger.debug(

                        "HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session");

                }

            }



            // Generate a HttpSession only if we need to

            if ((httpSession == null) && !httpSessionExistedAtStartOfRequest) {

                if (!allowSessionCreation) {

                    if (logger.isDebugEnabled()) {

                        logger.debug(

                            "Whilst ContextHolder contents have changed, the HttpSessionContextIntegrationFilter is prohibited from creating a HttpSession by the allowSessionCreation property being false");

                    }

                } else if (!contextObject.equals(ContextHolder.getContext())) {

                    if (logger.isDebugEnabled()) {

                        logger.debug(

                            "HttpSession being created as ContextHolder contents are non-default");

                    }



                    try {

                        httpSession = ((HttpServletRequest) request).getSession(true);

                    } catch (IllegalStateException ignored) {}

                } else {

                    if (logger.isDebugEnabled()) {

                        logger.debug(

                            "HttpSession still null, but ContextHolder has not changed from default: ' "

                            + ContextHolder.getContext()

                            + "'; not creating HttpSession or storing ContextHolder contents");

                    }

                }

            }



            // If HttpSession exists, store current ContextHolder contents

            if (httpSession != null) {

                httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,

                    ContextHolder.getContext());



                if (logger.isDebugEnabled()) {

                    logger.debug("Context stored to HttpSession: '"

                        + ContextHolder.getContext() + "'");

                }

                SecureContextImpl sec_context = (SecureContextImpl)ContextHolder.getContext();

                if (sec_context != null && (sec_context.getAuthentication() != null)) {

                    //String username = ((UserDetails)sec_context.getAuthentication().getDetails()).getUsername().substring(0,16);

                    String username = (String)sec_context.getAuthentication().getPrincipal();

                    User alfuser = null;

                    WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(httpSession.getServletContext());

                    ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);

                    AuthenticationService authService = (AuthenticationService) ctx.getBean("authenticationService");

                    TransactionService transactionService = serviceRegistry.getTransactionService();

                    UserTransaction tx = transactionService.getUserTransaction();

                    PersonService personService = (PersonService)ctx.getBean("personService");

               

                    try {

                  tx.begin();

                  //personService.setCreateMissingPeople(true);

                  String currentTicket = authService.getCurrentTicket();

                        alfuser =  new User(username,currentTicket,personService.getPerson(username));

                        NodeService nodeService = serviceRegistry.getNodeService();

                        //personService.setCreateMissingPeople(false);

                        NodeRef homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(username),

                                ContentModel.PROP_HOMEFOLDER);

                        alfuser.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);

                  }

               }

                    httpSession.setAttribute(ALF_SECURITY_CONTEXT_KEY,alfuser);

                }


            }



            // Remove ContextHolder contents

            ContextHolder.setContext(null);



            if (logger.isDebugEnabled()) {

                logger.debug(

                    "ContextHolder set to null as request processing completed");

            }

        }

    }

}

Second question: we had to change the class org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.java at line 444 in method getAuthorizations to avoid a classCastExceptionError:

java.lang.ClassCastException: java.lang.String
        at org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.getAuthorisations(PermissionServiceImpl.java:444)
        at org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.hasPermission(PermissionServiceImpl.java:363)
        at org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.hasPermission(PermissionServiceImpl.java:582)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
        at $Proxy64.hasPermission(Unknown Source)
        at org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoter.vote(ACLEntryVoter.java:316)
        at net.sf.acegisecurity.vote.AffirmativeBased.decide(AffirmativeBased.java:69)
        at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:394)
        at net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:77)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:40)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
        at $Proxy66.getProperty(Unknown Source)
at org.alfresco.web.app.servlet.Cas2AlfrescoContextIntegrationFilter.doFilter(Cas2AlfrescoContextIntegrationFilter.java:275)
  …

This is due, for what we can understand, to a mismatch between line 201 of casAuthenticationProvider, which state

return new CasAuthenticationToken(this.key, response.getUser(),

            authentication.getCredentials(), userDetails.getAuthorities(),

            userDetails, response.getProxyList(),

            response.getProxyGrantingTicketIou());
(note the second parameter response.getUser which returns a String)
and line 444 of org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.java where auth is of type CasAuthenticationToken and so auth.getPrincipal() returns a String and cannot be casted to User (see code inside constructor of CasAuthenticationToken.
To solve this problem we changed method getAuthorisations in PermissionServiceImpl.java this way:

    private Set<String> getAuthorisations(Authentication auth, NodeRef nodeRef)

    {

        HashSet<String> auths = new HashSet<String>();

        // No authenticated user then no permissions

        if (auth == null)

        {

            return auths;

        }

        // TODO: Refactor and use the authentication service for this.

        //User user = (User) auth.getPrincipal();

       

        //auths.add(user.getUsername());

        auths.add((String)auth.getPrincipal());

        for (GrantedAuthority authority : auth.getAuthorities())

        {

            auths.add(authority.getAuthority());

        }

        if (dynamicAuthorities != null)

        {

            for (DynamicAuthority da : dynamicAuthorities)

            {

//               if (da.hasAuthority(nodeRef, user.getUsername()))

               if (da.hasAuthority(nodeRef,(String)auth.getPrincipal()))

                {

                    auths.add(da.getAuthority());

                }

            }

        }

        auths.addAll(authorityService.getAuthorities());

        return auths;

    }

Does it seem meaningful or we missed the all thing?javascript:emoticon('Smiley Very Happy')
Thank you in advance for your help?

Davide & Emanuele
5 REPLIES 5

ribz33
Champ on-the-rise
Champ on-the-rise
Have you find a solution ?
Your Casifying of alfresco is it working now?

Im trying to do same thing…

Thx

escaglia
Champ in-the-making
Champ in-the-making
Yes it was working,
provided that we change the class org.alfresco.repo.security.permissions.impl.PermissionServiceImpl.java changing the method getAuthorisations as explained in the post.
We used Alfresco vers. 1.3, I don't know if it's still working with 1.4
Good luck,
Emanuele

dpalmeira
Champ in-the-making
Champ in-the-making
Hi,

I'm trying cas + user & group importing using ldap, but I get an exception after login into cas, just when redirect to alfresco occur

I dont know how can I fix it…


org.alfresco.error.AlfrescoRuntimeException: Not implemented
at org.alfresco.repo.security.authentication.DefaultMutableAuthenticationDao.loadUserByUsername(DefaultMutableAuthenticationDao.java:402)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy6.loadUserByUsername(Unknown Source)
at net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator.getUserDetails(DaoCasAuthoritiesPopulator.java:58)
at net.sf.acegisecurity.providers.cas.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:197)
at net.sf.acegisecurity.providers.cas.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:165)
at net.sf.acegisecurity.providers.ProviderManager.doAuthentication(ProviderManager.java:159)
at net.sf.acegisecurity.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
at net.sf.acegisecurity.ui.cas.CasProcessingFilter.attemptAuthentication(CasProcessingFilter.java:109)
at net.sf.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:287)
at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
at…

Another point is that I'm using passthru authenticator, but I'm not sure if it's the cause, because if I use alfresco authenticator widthout ldap sync, it's works !

I'm confussed about that.

can somebody help me?

thx

dpalmeira
Champ in-the-making
Champ in-the-making
I found the solution….

I had a DefaultMutableAuthenticationDao defined already in ldap-authentication-context.xml

So I commented it and wuaaaalaaa ! it works fine !

Smiley Tongue

andrepra
Champ in-the-making
Champ in-the-making
This is the solution i use

http://issues.alfresco.com/browse/AWC-952

Andrea