Activit与LDAP的集成

在Activiti的User Guide(5.9)里, 有介绍activiti与LDAP的集成示例. 

 

 

<userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/>

This also works similar for candidate users and groups:

<userTask id="task" name="My Task" activiti:candidateUsers="${ldapService.findAllSales()}"/>

Note that this will only work if the return type of the invoked methods is String or Collection<String> (for candidate users and groups):

            
public class FakeLdapService {
  
  public String findManagerForEmployee(String employee) {
    return "Kermit The Frog";
  }
  
  public List<String> findAllSales() {
    return Arrays.asList("kermit", "gonzo", "fozzie");
  }

}

 

 

ldapService是在spring容器里的bean.

这种方法比较适用于单纯的为一个task指定assignee或者candidateUsers, 也就是一个或多个user.

但是对于有group关联的情况就无能为力 了.

 

 

还有一种集成方式是通过改变activiti里的UserManager和GroupManager实现来集成ldap.

这种实现方式会用到Apache LDAP API(1.0.0-M12). 

 

首先. 改变activiti配置文件.

 

activiti.cfg-mem-ldap.xml

 

<?xml version="1.0" encoding="UTF-8"?>

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

  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
  
  	<property name="jdbcUrl" value="jdbc:h2:tcp://localhost/activiti" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />
    <property name="databaseSchemaUpdate" value="true" />
    
    <property name="customSessionFactories">
      <list>
        <bean class="nanquan.test.ldap.LDAPUserManagerFactory">
          <constructor-arg ref="ldapConnectionParams" />
        </bean>
        <bean class="nanquan.test.ldap.LDAPGroupManagerFactory">
          <constructor-arg ref="ldapConnectionParams" />
        </bean>
      </list>
    </property>
    
  </bean>
  
  <bean id="ldapConnectionParams" class="nanquan.test.ldap.LDAPConnectionParams
">
    <property name="ldapServer" value="LDAP_IP" />
    <property name="ldapPort" value="389" />
    <property name="ldapUser" value="uid=admin,dc=users,dc=its" />
    <property name="ldapPassword" value="PASSWORD" />
  </bean> 

</beans>
 

在customSessionFactories属性里配置我们自定义的factories.

 

下面是两个factories和他们的服务对象.

 

LDAPUserManagerFactory.

 

 

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.UserManager;

public class LDAPUserManagerFactory implements SessionFactory {

	private LDAPConnectionParams connectionParams;
	
	public LDAPUserManagerFactory(LDAPConnectionParams params) {
		this.connectionParams = params;
	}
	
	@Override
  public Class<?> getSessionType() {
	  return UserManager.class;
  }

	@Override
  public Session openSession() {
	  return new LDAPUserManager(connectionParams);
  }

}

 

LDAPUserManager.

 

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.impl.persistence.entity.UserManager;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.shared.ldap.model.cursor.EntryCursor;
import org.apache.directory.shared.ldap.model.entry.Attribute;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.message.BindRequestImpl;
import org.apache.directory.shared.ldap.model.message.BindResponse;
import org.apache.directory.shared.ldap.model.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.model.message.SearchScope;
import org.apache.directory.shared.ldap.model.name.Dn;

public class LDAPUserManager extends UserManager {

//	private static final String USER_GROUP = "ou=users,ou=system";
	private static final String USER_GROUP = "dc=users,DC=ITS";

	private LDAPConnectionParams connectionParams;

	public LDAPUserManager(LDAPConnectionParams params) {
		this.connectionParams = params;
	}

	@Override
	public User createNewUser(String userId) {
		throw new ActivitiException(
				"LDAP user manager doesn't support creating a new user");
	}

	@Override
	public void insertUser(User user) {
		throw new ActivitiException(
				"LDAP user manager doesn't support inserting a new user");
	}

	@Override
	public void updateUser(User updatedUser) {
		throw new ActivitiException(
				"LDAP user manager doesn't support updating a user");
	}

	@Override
	public UserEntity findUserById(String userId) {
		throw new ActivitiException(
				"LDAP user manager doesn't support finding a user by id");
	}

	@Override
	public void deleteUser(String userId) {
		throw new ActivitiException(
				"LDAP user manager doesn't support deleting a user");
	}

	@Override
	public List<User> findUserByQueryCriteria(Object query, Page page) {

		List<User> userList = new ArrayList<User>();

		// Query is a UserQueryImpl instance
		UserQueryImpl userQuery = (UserQueryImpl) query;
		StringBuilder searchQuery = new StringBuilder();
		if (StringUtils.isNotEmpty(userQuery.getId())) {
			searchQuery.append("(uid=").append(userQuery.getId()).append(")");

		} else if (StringUtils.isNotEmpty(userQuery.getLastName())) {
			searchQuery.append("(sn=").append(userQuery.getLastName())
					.append(")");

		} else {
			searchQuery.append("(uid=*)");
		}
		LdapConnection connection = LDAPConnectionUtil
				.openConnection(connectionParams);
		try {
			EntryCursor search = connection.search(USER_GROUP,
					searchQuery.toString(), SearchScope.ONELEVEL, "*");
			while (search.next()) {
				User user = new UserEntity();
				Entry entry = search.get();
				Collection<Attribute> attributes = entry.getAttributes();
				for (Attribute attribute : attributes) {
					String key = attribute.getId();
					if ("uid".equalsIgnoreCase(key)) {
						user.setId(attribute.getString());

					} else if ("sn".equalsIgnoreCase(key)) {
						user.setLastName(attribute.getString());

					} else if ("cn".equalsIgnoreCase(key)) {
						user.setFirstName(attribute.getString().replace("cn:", "").trim());
//						user.setFirstName(attribute.getString().substring(0,
//								attribute.getString().indexOf(" ")));
					}
				}
				userList.add(user);
			}

			search.close();

		} catch (Exception e) {
			e.printStackTrace();
			throw new ActivitiException("LDAP connection search failure", e);
		}

		LDAPConnectionUtil.closeConnection(connection);

		return userList;
	}

	@Override
	public long findUserCountByQueryCriteria(Object query) {
		return findUserByQueryCriteria(query, null).size();
	}

	@Override
	public Boolean checkPassword(String userId, String password) {
		boolean credentialsValid = false;
		LdapNetworkConnection connection = new LdapNetworkConnection(
				connectionParams.getLdapServer(),
				connectionParams.getLdapPort());
		try {
//			connection.bind("uid=" + userId + ","
//					+ USER_GROUP, password);
			BindRequestImpl bindRequest = new BindRequestImpl();
			Dn dn = new Dn("uid=" + userId + ","
					+ USER_GROUP);
			bindRequest.setDn(dn );
			bindRequest.setCredentials(password);
			BindResponse response = connection.bind(bindRequest);
			if (response.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS) {
				credentialsValid = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ActivitiException("LDAP connection bind failure", e);
		}

		LDAPConnectionUtil.closeConnection(connection);

		return credentialsValid;
	}
}

 

 

LDAPGroupManagerFactory.

 

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.GroupManager;

public class LDAPGroupManagerFactory implements SessionFactory {

	private LDAPConnectionParams connectionParams;
	
	public LDAPGroupManagerFactory(LDAPConnectionParams params) {
		this.connectionParams = params;
	}
	
	@Override
  public Class<?> getSessionType() {
	  return GroupManager.class;
  }

	@Override
  public Session openSession() {
	  return new LDAPGroupManager(connectionParams);
  }

}

 

 

LDAPGroupManager 

 

 

 

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.GroupManager;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.shared.ldap.model.cursor.EntryCursor;
import org.apache.directory.shared.ldap.model.entry.Attribute;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.message.SearchScope;

public class LDAPGroupManager extends GroupManager {

//	private static final String USER_ENTRY = "ou=users,ou=system";
//	private static final String GROUP_ENTRY = "ou=groups,ou=system";
	
	private static final String USER_ENTRY = "dc=users,DC=ITS";
	private static final String GROUP_ENTRY = "dc=groups,DC=ITS";

	private LDAPConnectionParams connectionParams;

	public LDAPGroupManager(LDAPConnectionParams params) {
		this.connectionParams = params;
	}

	@Override
	public Group createNewGroup(String groupId) {
		throw new ActivitiException(
				"LDAP group manager doesn't support creating a new group");
	}

	@Override
	public void insertGroup(Group group) {
		throw new ActivitiException(
				"LDAP group manager doesn't support inserting a new group");
	}

	@Override
	public void updateGroup(Group updatedGroup) {
		throw new ActivitiException(
				"LDAP group manager doesn't support updating a new group");
	}

	@Override
	public void deleteGroup(String groupId) {
		throw new ActivitiException(
				"LDAP group manager doesn't support deleting a new group");
	}

	@Override
	public List<Group> findGroupByQueryCriteria(Object query, Page page) {
		List<Group> groupList = new ArrayList<Group>();

		// Query is a GroupQueryImpl instance
		GroupQueryImpl groupQuery = (GroupQueryImpl) query;
		StringBuilder searchQuery = new StringBuilder();
		if (StringUtils.isNotEmpty(groupQuery.getId())) {
			searchQuery.append("(cn=").append(groupQuery.getId()).append(")");

		} else if (StringUtils.isNotEmpty(groupQuery.getName())) {
			searchQuery.append("(cn=").append(groupQuery.getName()).append(")");

		} else if (StringUtils.isNotEmpty(groupQuery.getUserId())) {
			searchQuery.append("(uniqueMember= uid=")
					.append(groupQuery.getUserId())
					.append("," + USER_ENTRY + ")");

		} else {
			searchQuery.append("(cn=*)");
		}
		LdapConnection connection = LDAPConnectionUtil
				.openConnection(connectionParams);
		try {
			EntryCursor search = connection.search(GROUP_ENTRY,
					searchQuery.toString(), SearchScope.ONELEVEL, "*");

			while (search.next()) {
				Group group = new GroupEntity();
				Entry entry = search.get();
				Collection<Attribute> attributes = entry.getAttributes();
				for (Attribute attribute : attributes) {
					String key = attribute.getId();
					if ("cn".equalsIgnoreCase(key)) {
						group.setId(attribute.getString());
						group.setName(attribute.getString());
					}
				}
				groupList.add(group);
			}

			search.close();

		} catch (Exception e) {
			throw new ActivitiException("LDAP connection search failure", e);
		}

		LDAPConnectionUtil.closeConnection(connection);

		return groupList;
	}

	@Override
	public long findGroupCountByQueryCriteria(Object query) {
		return findGroupByQueryCriteria(query, null).size();
	}

	@Override
	public GroupEntity findGroupById(String groupId) {
		throw new ActivitiException(
				"LDAP group manager doesn't support finding a group by id");
	}

	@Override
	public List<Group> findGroupsByUser(String userId) {
		List<Group> groupList = new ArrayList<Group>();

		LdapConnection connection = LDAPConnectionUtil
				.openConnection(connectionParams);
		try {
			EntryCursor search = connection.search(GROUP_ENTRY,
					"(uniqueMember= uid=" + userId + "," + USER_ENTRY + ")",
					SearchScope.ONELEVEL, "*");

			while (search.next()) {
				Group group = new GroupEntity();
				Entry entry = search.get();
				Collection<Attribute> attributes = entry.getAttributes();
				for (Attribute attribute : attributes) {
					String key = attribute.getId();
					if ("cn".equalsIgnoreCase(key)) {
						group.setId(attribute.getString());
						group.setName(attribute.getString());
					}
				}
				groupList.add(group);
			}

			search.close();

		} catch (Exception e) {
			throw new ActivitiException("LDAP connection search failure", e);
		}

		LDAPConnectionUtil.closeConnection(connection);

		return groupList;
	}
}

 

LDAPConnectionParams 

 

 

public class LDAPConnectionParams {
	
	private String ldapServer;
	private int ldapPort;
	private String ldapUser;
	private String ldapPassword;
	
	public String getLdapServer() {
  	return ldapServer;
  }
	public void setLdapServer(String ldapServer) {
  	this.ldapServer = ldapServer;
  }
	public int getLdapPort() {
  	return ldapPort;
  }
	public void setLdapPort(int ldapPort) {
  	this.ldapPort = ldapPort;
  }
	public String getLdapUser() {
  	return ldapUser;
  }
	public void setLdapUser(String ldapUser) {
  	this.ldapUser = ldapUser;
  }
	public String getLdapPassword() {
  	return ldapPassword;
  }
	public void setLdapPassword(String ldapPassword) {
  	this.ldapPassword = ldapPassword;
  }
}

 

LDAPConnectionUtil 

 

import org.activiti.engine.ActivitiException;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;

public class LDAPConnectionUtil {

	public static LdapConnection openConnection(LDAPConnectionParams connectionParams) {
		LdapConnection connection = new LdapNetworkConnection(connectionParams.getLdapServer(), connectionParams.getLdapPort());
	  try {
	    connection.bind(connectionParams.getLdapUser(), connectionParams.getLdapPassword());
    } catch (Exception e) {
	    throw new ActivitiException("LDAP connection open failure", e);
    }
	  return connection;
	}
	
	public static void closeConnection(LdapConnection connection) {
		try {
	  	connection.unBind();
	  	connection.close();
	  } catch (Exception e) {
	    throw new ActivitiException("LDAP connection close failure", e);
    }
	}
}

 

简单的测试类:

LdapTest 

 

 

public class LdapTest {
	
	public static void main(String[] args) {
		String path = "activiti.cfg-mem-ldap.xml";
		Resource resource = new ClassPathResource(path);
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		
		LDAPConnectionParams connectionParams = (LDAPConnectionParams) beanFactory.getBean("ldapConnectionParams");
		LDAPUserManager userManager = new LDAPUserManager(connectionParams);
		LDAPGroupManager groupManager = new LDAPGroupManager(connectionParams);
		
		Boolean checkPassword = userManager.checkPassword("admin", "passw0rd");
		System.out.println(checkPassword);
		
		UserQueryImpl query = new UserQueryImpl();
		query.userId("admin");
		long size = userManager.findUserCountByQueryCriteria(query);
		System.out.println(size);
		
		GroupQueryImpl groupQuery = new GroupQueryImpl();
		groupQuery.groupId("AdminGroup");
		long groupSize = groupManager.findGroupCountByQueryCriteria(groupQuery);
		System.out.println(groupSize);
		
	}

}

 

执行一下看看是否可以正常执行.

 

需要注意的是

 

private static final String USER_GROUP = "dc=users,DC=ITS";

 

 

private static final String USER_ENTRY = "dc=users,DC=ITS";
private static final String GROUP_ENTRY = "dc=groups,DC=ITS";
 

这几个常量需要根据实际情况来调整, 当然最好可以放到配置文件里.

 

 

参考自

http://code.google.com/p/activitiinaction/source/browse/trunk/bpmn-examples/src/main/resources/chapter10/ldap/activiti.cfg-mem-ldap.xml?spec=svn205&r=205

这里面用到的Apache LDAP API比较老, 我做了一些调整.

 

 

你可能感兴趣的:(Activiti,集成,LDAP)