17.集成LDAP
企业通常已经在LDAP系统各种保存了用户和群组信息。 自从5.14版本开始,Activiti提供了一种解决方案, 通过简单的配置就可以告知activiti如何连接LDAP。
在Activiti 5.14之前,Activiti就已经可以集成LDAP了。 然后,5.14的配置简单了很多。 不过,配置LDAP的“老”办法依然有效。更确切的说, 简化的配置其实是基于“老”方法的封装。
用法
要想在你的项目中集成LDAP, 在pom.xml中添加如下依赖:
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-ldap</artifactId>
<version>latest.version</version>
</dependency>
用例
集成LDAP目前有两大用例:
通过IdentityService进行认证。比如,使用Activiti Explorer 通过LDAP登录。
获得用户的组。这在查询用户可以看到哪些任务时非常重要。 (比如,任务分配给一个候选组)。
配置
集成LDAP是通过向流程引擎配置章节中的configurators
注入 org.activiti.ldap.LDAPConfigurator
的实例来实现的。 这个类是高度可扩展的: 如果默认的实现不符合用例的话, 可以很容易的重写方法,很多依赖的bean都是可插拔的。
这时一个实例配置(注意:当然, 通过代码创建引擎时,是非常简单的)。 现在不用担心所有参数,我们会在下一章详细讨论。
<bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">
...
<property name="configurators">
<list>
<bean class="org.activiti.ldap.LDAPConfigurator">
<!-- Server connection params -->
<property name="server" value="ldap://localhost" />
<property name="port" value="33389" />
<property name="user" value="uid=admin, ou=users, o=activiti" />
<property name="password" value="pass" />
<!-- Query params -->
<property name="baseDn" value="o=activiti" />
<property name="queryUserByUserId" value="(&(objectClass=inetOrgPerson)(uid={0}))" />
<property name="queryUserByFullNameLike" value="(&(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))" />
<property name="queryGroupsForUser" value="(&(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />
<!-- Attribute config -->
<property name="userIdAttribute" value="uid" />
<property name="userFirstNameAttribute" value="cn" />
<property name="userLastNameAttribute" value="sn" />
<property name="groupIdAttribute" value="cn" />
<property name="groupNameAttribute" value="cn" />
</bean>
</list>
</property>
</bean>
属性
下面是org.activiti.ldap.LDAPConfigurator
可以配置的属性:
Table 17.1.LDAP配置属性
属性名 | 描述 | 类型 | 默认值 |
---|---|---|---|
server | LDAP服务器地址。比如'ldap://localhost:33389' | String | |
port | LDAP运行的端口 | int | |
user | 连接LDAP使用的账号 | String | |
password | 连接LDAP使用的密码 | String | |
initialContextFactory | 连接LDAP使用的InitialContextFactory名称 | String | com.sun.jndi.ldap.LdapCtxFactory |
securityAuthentication | 连接LDAP时设置的'java.naming.security.authentication'属性值 | String | simple |
customConnectionParameters | 可以设置那些没有对应setter的连接参数。 参考http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html中的自定义属性。 这些属性用来配置连接池,特定的安全设置,等等。 所有提供的参数都会用来创建LDAP连接。 | Map<String, String> | |
baseDn | 搜索用户和组的基“显著名称”(DN) | String | |
userBaseDn | 搜索用户基于的'distinguished name' (DN)。如果没有提供,会使用baseDn(参考上面) | String | |
groupBaseDn | 搜索群组基于的'distinguished name' (DN)。如果没有提供,会使用baseDn(参考上面) | String | |
searchTimeLimit | 搜索LDAP的超时时间,单位毫秒。 | long | 一小时 |
queryUserByUserId | 使用用户id搜索用户的查询语句。 比如:(&(objectClass=inetOrgPerson)(uid={0})) 这里,LDAP中所有包含'inetOrgPerson'类的 匹配'uid'属性的值都会返回。 如例子中所示,{0}会被用户id替换。 如果只设置一个查询无法满足特定的LDAP设置, 可以选择使用LDAPQueryBuilder, 这样就会提供比单纯使用查询增加更多功能。 | string | |
queryUserByFullNameLike | 使用全名搜索用户的查询语句。 比如:(& (objectClass=inetOrgPerson) (|({0}=*{1}*)({2}=*{3}*)) ) 这里,LDAP中所有包含'inetOrgPerson'类的 匹配first name和last name的值都会返回。 注意{0}会替换为firstNameAttribute(如上所示),{1}和{3}是搜索内容, {2}是lastNameAttribute。 如果只设置一个查询无法满足特定的LDAP设置, 可以选择使用LDAPQueryBuilder, 这样就会提供比单纯使用查询增加更多功能。 | string | |
queryGroupsForUser | 使用搜索指定用户的组的查询语句。 比如:(&(objectClass=groupOfUniqueNames)(uniqueMember={0})) 这里,LDAP中所有包含'groupOfUniqueNames'类的 提供的DN(匹配用户的DN)是'uniqueMember'的记录都会返回。 像例子中演示的那样,{0}会替换为用户id。 如果只设置一个查询无法满足特定的LDAP设置, 可以选择使用LDAPQueryBuilder, 这样就会提供比单纯使用查询增加更多功能。 | string | |
userIdAttribute | 匹配用户id的属性名。 这个属性用来在查找用户对象时 关联LDAP对象与Activiti用户对象之间的关系。 | string | |
userFirstNameAttribute | 匹配first name的属性名。 这个属性用来在查找用户对象时 关联LDAP对象与Activiti用户对象之间的关系。 | string | |
userLastNameAttribute | 匹配last name的属性名。 这个属性用来在查找用户对象时 关联LDAP对象与Activiti用户对象之间的关系。 | string | |
groupIdAttribute | 匹配组id的属性名。 这个属性用来在查找组对象时 关联LDAP对象与Activiti组对象之间的关系。 | string | |
groupNameAttribute | 匹配组名的属性名。 这个属性用来在查找组对象时 关联LDAP对象与Activiti组对象之间的关系。 | String | |
groupTypeAttribute | 匹配组名的属性类型。 这个属性用来在查找组对象时 关联LDAP对象与Activiti组对象之间的关系。 | String |
下列属性用在希望修改默认行为 或修改组缓存的情况:
Table 17.2.高级属性
属性名 | 描述 | 类型 | 默认值 |
---|---|---|---|
ldapUserManagerFactory | 设置LDAPUserManagerFactory的自定义实例,如果默认实现不满足需求。 | LDAPUserManagerFactory的实例 | |
ldapGroupManagerFactory | 设置LDAPGroupManagerFactory的自定义实例,如果默认实现不满足需求。 | LDAPGroupManagerFactory的实例 | |
ldapMemberShipManagerFactory | 设置LDAPMembershipManagerFactory的自定义实例,如果默认实现不满足需求。 注意它不常用,因为正常情况下LDAP会自己管理关联关系。 | LDAPMembershipManagerFactory的实例 | |
ldapQueryBuilder | 设置自定义查询构造器,如果默认实现不满足需求。 LDAPQueryBuilder实例用在LDAPUserManager和LDAPGroupManager中, 执行对LDAP的查询。 默认实现会使用配置的queryGroupsForUser和queryUserById属性。 | org.activiti.ldap.LDAPQueryBuilder的实例 | |
groupCacheSize | 组缓存的大小。 这是一个LRU缓存,用来缓存用户的组, 可以避免每次查询用户的组时,都要访问LDAP。 如果值小于0,就不会创建缓存。 默认为-1,所以不会进行缓存。 | int | -1 |
groupCacheExpirationTime | 设置组缓存的过期时间,单位为毫秒。 当获取特定用户的组时,并且组缓存也启用了, 组会保存到缓存中,并使用这个属性设置的时间。 例如,当组在00:00被获取,过期时间为30分钟, 那么所有在00:30之后进行的查询都不会使用缓存, 而是再次去LDAP查询。因此,所以在00:00 - 00:30 进行的查询都会使用缓存。 | long | 1小时 |
注意,在使用活动目录(AD)时:Activiti论坛中的人们反映对于活动目录(AD), 'InitialDirContext'需要设置为Context.REFERRAL。可以通过上面描述的customConnectionParameters传递。
为Explorer集成LDAP
把上面的LDAP配置添加到
activiti-standalone-context.xml
中。把activiti-ldap jar放到WEB-INF/lib目录下
删除
demoDataGenerator
bean,因为它会尝试插入数据(集成LDAP不允许这么做)将下面的配置添加到
activiti-ui.context
的explorerApp
bean中:<property name="adminGroups">
<list>
<value>admin</value>
</list>
</property>
<property name="userGroups">
<list>
<value>user</value>
</list>
</property>
请使用你自己的配置替换其中的值。需要用到的数据是组的id(通过
groupIdAttribute
配置)。 上述配置会让'admin'组下的所有用户都成为Activiti Explorer的管理员,用户组也一样。 所有不匹配的组都会当做“分配”组, 这样任务就可以分配给他们。