Alfresco debugger in a VirtualBox VM

How to run the Alfresco Server Side debugger when running in an Ubuntu Virtual Box VM

Edit /opt/alfresco-3.4.d/tomcat/scripts/ctl.sh to add:
DISPLAY=:0.0
export DISPLAY

The other trick is to make sure that you type ‘xhost +’

You will need to do this in a shell window AND in the shell from which you restart alfresco

The Web Script /alfresco/service/api/javascript/debugger has responded with a status of 500 – Internal Error.

500 Description: An error inside the HTTP server which prevented it from fulfilling the request.

Message: 08090007 Wrapped Exception (with status template): Could not initialize class sun.awt.X11GraphicsEnvironment

Exception: java.lang.NoClassDefFoundError – Could not initialize class sun.awt.X11GraphicsEnvironment

CAS, Alfresco and WebDAV

Having successfully configured Alfresco (and Share) to authenticate using CAS – it’s documented here

The next challenge is to try and work out how to get this authentication working with webdav
Update:

One way to do this this is to bypass CAS and authenticate against the underlying CAS datastore directly by adding a new authentication component.

Of course this means that you are not using CAS but then as you are likely to be accessing WebDAV outside of the browser the single sign on capabilities are not particularly relevant

We use Drupal as our underlying CAS data store so there’s a bit of custom code here – you may be able to just configure the authentication chain if you’re using a different method e.g. LDAP

So in alfresco-global.properties add to the authentication chain:
authentication.chain=cas:external,localDrupal:drupal

While you’re there set up some database connection properties e.g.

drupal.db.driver=org.gjt.mm.mysql.Driver
drupal.db.username=drupal
drupal.db.password=drupal
drupal.db.url=jdbc:mysql://localhost:3306/drupal6

I’m not going to cover ensuring that you have access to the mysql database here. If it’s on a different machine you’ll need to configure MySQL as well as any firewall rules.

Next it’s time to tell Alfresco about the new component that you are creating so create the directory alfresco/subsystems/Authentication/drupal and add the following files:

drupal-authentication-context.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://www.springframework.org/schema/beans" 
xsi:schemalocation="http://www.springframework.org/schema/beans  
  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean class="org.apache.commons.dbcp.BasicDataSource" 
                       destroy-method="close" id="drupalDataSource">
       <property name="driverClassName" value="${drupal.db.driver}"/>
        <property name="url" value="${drupal.db.url}"/>
        <property name="username" value="${drupal.db.username}"/>
        <property name="password" value="${drupal.db.password}"/>
        <property name="validationQuery" value="SELECT 1"/>
        <property name="testOnBorrow" value="true"/>
        <property name="defaultAutoCommit" value="false"/>
        <property name="maxWait" value="5000"/>
    </bean>

    <bean class="mypackage.authentication.DrupalAuthenticationComponentImpl" 
id="drupalAuthenticationComponent" parent="authenticationComponentBase"> 
<property name="dataSource" ref="drupalDataSource"/>
        <property name="nodeService">
            <ref bean="nodeService"/>
        </property>
        <property name="personService">
            <ref bean="personService"/>
        </property>
        <property name="transactionService">
            <ref bean="transactionService"/>
        </property>
</bean>

      <!-- Wrapped Drupal authentication component to be used within subsystem -->
    <bean id="AuthenticationComponent">
        <property name="proxyInterfaces">
            <value>org.alfresco.repo.security.authentication.AuthenticationComponent</value>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="target">
            <ref bean="drupalAuthenticationComponent"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">${server.transaction.mode.default}</prop>
            </props>
        </property>
    </bean>
     <!-- Authentication service for authentication component chaining

     Note. the id of this bean must be 'localAuthenticationService' for it to
     be picked up, as an authentication service, by the
     Subsystem Chaining Authentication Service
    -->
    <bean id="localAuthenticationService">
        <property name="ticketComponent">
            <ref bean="ticketComponent"/>
        </property>
        <property name="authenticationComponent">
            <ref bean="drupalAuthenticationComponent"/>
        </property>
        <property name="sysAdminParams">
            <ref bean="sysAdminParams"/>
        </property>
    </bean>
</beans>

 

drupal-authentication.properties

drupal.db.driver=org.gjt.mm.mysql.Driver
drupal.db.username=drupal
drupal.db.password=drupal
drupal.db.url=jdbc:mysql://localhost:3306/drupal6

 

Then create the bean that is referenced from the config

package mypackage.cms.authentication;

import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.security.MessageDigest;

/**
 * Authenticates a user by Drupal.
 * <p/>
 * The authentication is done against the database table USERS and the
 * column NAME (username) and column PASS (MD5 password)
 * <p/>
 * Tested with Drupal 6
 *
 * @author martin.bergljung@ixxus.co.uk
 */
public class DrupalAuthenticationComponentImpl 
extends AbstractAuthenticationComponent implements ActivateableBean {
    public static final String GET_USER_PWD_SQL = "SELECT pass FROM users WHERE name=?";

    private final Log logger = LogFactory.getLog(getClass());

    /**
     * Spring JDBC template used to query or update a JDBC data source
     */
    private JdbcTemplate m_jdbcTemplate;

    /**
     * Is this bean active? I.e. should this part of the subsystem be used?
     */
    private boolean m_active = true;

    public DrupalAuthenticationComponentImpl() {
        super();
    }

    /**
     * Controls whether this bean is active. I.e. should this part of the subsystem be used?
     *
     * @param active <code>true</code> if this bean is active
     */
    public void setActive(boolean active) {
        m_active = active;
    }

    /**
     * Dependeny Injects the data source to be used for querying Drupal database
     *
     * @param dataSource the data source to use
     */
    public void setDataSource(DataSource dataSource) {
        m_jdbcTemplate = new JdbcTemplate(dataSource);
    }

    /*
    * (non-Javadoc)
    * @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
    */
    public boolean isActive() {
        return m_active;
    }

    /**
     * Authenticate against the Drupal database
     *
     * @param userName the username to authenticate
     * @param password the password to authenticate (passed in as plain text)
     * @throws AuthenticationException if authentication failed
     */
    @Override
    protected void authenticateImpl(String userName, char[] password) throws AuthenticationException {
        String userPwd = new String(password);

        // Generate an MD5 hash for the password as that is what we get back from Drupal
        // Get the value as hex
        String userPwdMd5 = DigestUtils.md5Hex(userPwd);

        if (logger.isDebugEnabled()) {
            logger.debug("About to authenticate user: " + userName + " with MD5 password: " + userPwdMd5);
        }

        try {
            String drupalPwdMd5 = m_jdbcTemplate.queryForObject(GET_USER_PWD_SQL, new Object[]{userName}, String.class);

            if (logger.isDebugEnabled()) {
                logger.debug("Got MD5 password from Drupal database: " + drupalPwdMd5);
            }

            if (StringUtils.isNotBlank(drupalPwdMd5)) {
                if (MessageDigest.isEqual(userPwdMd5.getBytes(), drupalPwdMd5.getBytes())) {
                    // Authentication has been successful.
                    // Set the current user, they are now authenticated.
                    setCurrentUser(userName);
                } else {
                    throw new AuthenticationException("Access denied for user: " + userName +
                            ", incorrect password provided.");
                }
            } else {
                throw new AuthenticationException(
                        "Password in Drupal database is blank, empty, or null for user: " + userName);
            }
        } catch (DataAccessException dae) {
            throw new AuthenticationException(
                    "Error getting password from Drupal database for user: " + userName +
                            ", user may not exist in the Drupal database", dae);
        }
    }

    @Override
    protected boolean implementationAllowsGuestLogin() {
        return true;
    }
}