在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比较老, 我做了一些调整.