在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";
这几个常量需要根据实际情况来调整, 当然最好可以放到配置文件里.
参考自
这里面用到的Apache LDAP API比较老, 我做了一些调整.