分类:Middleware, 数据库, 服务器端技术, 网页&平面设计, 计算机与互联网 作者: 秋天 时间: 12-02-2010
写一篇alfresco + liferay配置LDAP服务器管理用户数据,并使用CAS SSO server进行统一用户登录验证的文章。
最近开发公司的网站+内容工作流程管理系统,使用OS平台Alfresco创建公司内部资源管理,并通过Restfull APIor Web Service调用其内容,并在liferay的支持下创建公司网站并开发用户管理中心。
在尝试配置,alfresco + liferay的LDAP用户数据管理和SSO的时候,碰到很多问题,这里把具体流程和一些心得写下来,作为记录,也给有着同样的问题的朋友分享。
互联网上,包括Alfresco 和liferay的官方论坛和wiki,都有不少关于整合其产品到LDAP和SSO的相关介绍甚至Tutorial。但由于这些开源软件更新较快的原因,当前互联网上大部分关于配置alfresco + liferay到LDAP SSO的文章,都已不太适用。所以才会有编写这个教学的理由。
这里请注意,由于上面我提到的原因,如果你正在使用我们这里使用的当前最新版本的alfresco和liferay,如果你发现你在互联网上找到的其他资料和这里提到的信息有冲突,请以我这里提到的参数和方法为准。因为一些过时的配置方法在新版本中已经不再使用了。
第一课,在alfresco中使用LDAP服务器进行用户认证,并实现同步。
虽然我们最终的目的是使用SSO来进行中控认证,但是需要配置LDAP中的用户数据自动同步到alfresco数据库中,这里先将alfresco配置到使用LDAP,确认其可以进行用户认证和同步,之后SSO启用后关掉LDAP认证功能,只保留同步功能,就可以了。
由于liferay新版本中,LDAP和SSO的配置基本界面化,所以我们先配置alfresco。当你已经成功的在alfresco中整合SSO和开启LDAP用户同步功能后,再将liferay整合进去就会比较简单了。
简单说一下我这里使用的系统平台和版本:
- alfresco运行于Win7 OS ultimate 64bit,使用其绑定的内置tomcat6
- Mysql服务和liferay服务运行于另一台主机,使用windows 2003 32bit
- LDAP服务和Mysql运行于同一台服务器,LDAP服务器使用apacheDS
- alfresco 使用 "alfresco-community-tomcat-3.2r2"
- Liferay 使用 "liferay-portal-tomcat-6.0-5.2.3"
- Mysql使用的一个WAMP里面带的老版本5.1.23
- ApacheDS 1.5.5
- 另外还用到Eclipse 3.6 Galileo 做为alfresco的开发环境并加装apacheDS studio插件对apacheDS进行管理。
安装,配置Alfresco
首先是安装alfresco,由于不是这里的重点,简单说一下。去官方下载alfresco-community-tomcat-3.2r2解压到你需要安装alfresco的目录,我们这里放到:
C:\Alfresco
我们把这个目录叫做%alfresco_home%。解压完成后,这里只需要设置Mysql数据库链接。打开:
%alfresco_home%\tomcat\shared\classes\alfresco-global.properties
如果没有这个文件自己创建一个空的,跟其他alfresco配置文件一样,这里设置的内容会覆盖其默认设置。编辑此文件并添加:
# # Sample database connection properties #------------- db.name=[数据库名] db.username=[链接数据库使用的用户名] db.password=[该用户的密码] db.host=[主机名称] db.port=[端口]
设置完成后保存。然后去下载MYSQL的JDBC connector,我这里使用mysql-connector-java-5.1.7-bin.jar,将该jar放到tomcat的lib下:
%alfresco_home%\tomcat\lib
这两步完成后alfresco应该就可以正确的使用mysql作为其数据库了。这里注意一下,以前的老版本alfresco需要自己创建数据库结构,就是将.sql文件的内容导入到数据库中,而现在的新版本已经不需要该步骤了。程序在第一次运行的时候,会自动检测数据库中表结构,如果没有表,会自动创建。现在双击alf_start.bat启动alfresco并注意查看log内容,如果看到如下:
15:20:26,657 INFO [org.alfresco.repo.domain.schema.SchemaBootstrap] Schema managed by database dialect org.hibernate.dialect.MySQLInnoDBDialect.
就说明mysql数据连接成功了,由于第一次运行的时候需要创建表结构,所以会比较慢,注意查看log可以看到其具体信息。
在进行设置的过程中,会多次启动和重启alfresco,如果你的机器配置比较好,可以在这里设置一下JAVA OPT性能参数,让tomcat使用更多的内存,这样会快很多。打开:
C:\Alfresco\alfresco.bat
并找到:
rem Set any default JVM options set JAVA_OPTS= ...
将 JAVA_OPTS中的内存使用按照你机器配置情况进行修改,我这里设置为:
set JAVA_OPTS=-Xms512m -Xmx1024m -Xss96k -XX:MaxPermSize=256m
安装LDAP服务器和示例数据
alfresco安装成功后,开始安装apache DS。这里没有太多好说的,按照默认设置安装即可。安装完成后,打开你的eclipse,安装ApacheDS stuido,使用update功能,添加这个site: http://directory.apache.org/studio/update/1.x 并进行更新。
更新完成后,重启eclipse并切换到LDAP视图,在LDAP connections窗口中添加一个连接。连接到你安装好的apacheDS服务。
连接成功后,双击该连接连接到服务器。在LDAP Browser中将会看到目录结构。如下图:
能看到目录结构,代表apacheDS安装成功了。
接下来,进行最重要的一步,配置alfresco使用我们安装的LDAP服务器进行用户认证,并同步用户数据到alfresco自己的服务器。
这里需要注意,alfresco在3.2版本后,针对其authentication subsystem部分做了很大的变动。如果你在网上发现其他教学在设置LDAP时使用完全不同的方法,那是因为其使用的是老版本。在老版本的alfresco中,需要自己编写Spring bean的context文件来进行LDAP配置,而在3.2 中LDAP已经是内置支持的Subsystem的一部分。默认的Spring context设置已经编写好,并且不需要用户手动进行任何的改动。用户所要做的,只是在global configure中开启相应的Subsystem支持,并且编写其配置文件即可。
LDAP认证方式,只是alfresco subsystems中的一部分,关于alfresco的其他subsystem和其原理,请看官方WIKI上关于alfresco subsystems的介绍。
在开始配置alfresco LDAP认证方式之前,我们先在LDAP服务器中增加我们需要用到得sample account,做为测试用途。
这里简单叙述一下LDAP中的目录结构和数据情况。我们将用户信息存放在apacheDS中的,ou=users,ou=system中。这里cn=%username, cn的objectClass需:
inetOrgPerson (structural) organizationalPerson (structural) person (structural) top (abstract)
cn= 用户名 (做为匹配用途) sn= 用户的lastname givenName= 用户的givenname mail= email地址 o= 用户的organization telephoneNumber= 电话号码 uid= 用户名(做为认证用途) userPassword= 用户密码
organizationalUnit (structural) top (abstract)
cn= 组名 member= 包含成员的用户名 (需要目录结构全称,比如"cn=admin,ou=users,ou=system")
现在我们按照我们上面设计的结构,在LDAP服务器中实施。在eclipse中创建一个ldif文件,这里我叫他sample-structure.ldif内容如下:
dn: cn=admin,ou=users,ou=system objectclass: inetOrgPerson sn: admin cn: admin userPassword: admin telephoneNumber: 1234567890 uid: admin givenName: admin mail: admin@company.com o: Company Software Inc. dn: cn=samuel,ou=users,ou=system objectclass: inetOrgPerson sn: Tian cn: samuel userPassword: 123456 telephoneNumber: 1234567890 uid: samuel givenName: tian mail: sam@satech.com.au o: Company Software Inc. dn: cn=Group One,ou=groups,ou=system objectclass: groupOfNames cn: Group One member: cn=samuel,ou=users,ou=system dn: cn=Group Two,ou=groups,ou=system objectclass: groupOfNames cn: Group Two member: cn=Group One,ou=groups,ou=system member: cn=admin,ou=users,ou=system
这里需要注意每个单元之间的空行是必须的,并且在最后一行需要保留空行,我这里由于插件的限制没法在最后空行。
以上结果完全运行成功后,在LDAP Browser里面展开ou=system中的ou=groups和ou=users,就可以看到如下图所示的结构了。
现在我们的LDAP服务器中就已经具备了我们这里所需的存放用户组和用户的节点和两个测试使用的账户和组。这里注意一下,可以看到我们在ou=users中设置了和alfresco默认数据库中相同的管理员账号:admin。当admin登陆成功后,将具备和alfresco中admin同样的系统管理员权限,便于我们查看系统中的用户数据,来证明我们的LDAP认证和同步功能是否配置成功。
alfresco的LDAP authentication subsystem支持指定特定用户为管理员,所以其实这里不一定非要建立一个admin,我这里使用admin只是方便起见。
配置Alfresco支持LDAP用户认证并实现同步
好,下面就开始配置alfresco支持LDAP认证了。打开alfresco的gloabal config文件:
%alfresco_home%\tomcat\shared\classes\alfresco-global.properties
找到:
# # The default authentication chain # To configure external authentication subsystems see: # http://wiki.alfresco.com/wiki/Alfresco_Authentication_Subsystems #------------- authentication.chain=alfrescoNtlm1:alfrescoNtlm
我们这里需要设置authentication.chain的值,注意这里默认的"alfrescoNtlm1:alfrescoNtlm"代表alfresco的内置认证方式。
后面的alfrescoNtlm代表这个认证是alfrescoHtlm类的一个实例,前面的alfrescoNtlm1代表这个认证的ID,这个ID是自己指定的,但是需要配合目录结构。
这里我们创建一个LDAP认证类的实例,取名为myldap。所以在上面的authentication.chain后面加上myldap:ldap:
authentication.chain=myldap:ldap
不同认证项目之间可以用逗号分隔。但是在没有设置passthru之前不建议搞两个否则就会需要认证两次。这里我们用我们新的myldap这个用户认证代替默认的alfresco内置用户认证。全局配置中做好设置后,需要在相应的目录编写一个properties设置文件。
如果你习惯使用eclipse来进行编辑,建立一个新的项目,在该项目下建立一个properties文件。在如下位置:
$project_root$\config\alfresco\extension\subsystems\Authentication\ldap\myldap\ldap-synchronisation.properties
这里的ldap目录后面的myldap目录,需要和前面的认证项的ID相匹配,如果你使用了不同的认证ID,这里需要做相应的修改。
ldap-synchronisation.properties内容如下: (需要注意的一些个配置选项我稍作翻译和说明)
# This flag enables use of this LDAP subsystem for authentication. It may be
# that this subsytem should only be used for synchronization, in which case
# this flag should be set to false.
# 选择是否使用LDAP来进行用户认证。这里我们选择true,等SSO设置完成后,这里改为false。
#
ldap.authentication.active=true
#
# This properties file brings together the common options for LDAP authentication rather than editing the bean definitions
# 是否允许匿名用户登录,按照你的情况选择,这里我们选择false
#
ldap.authentication.allowGuestLogin=false
# How to map the user id entered by the user to that passed through to LDAP
# - simple
# - this must be a DN and would be something like
# uid=%s,ou=People,dc=company,dc=com
# - digest
# - usually pass through what is entered
# %s
# If not set, an LDAP query involving ldap.synchronization.personQuery and ldap.synchronization.userIdAttributeName will
# be performed to resolve the DN dynamically. This allows directories to be structured and doesn't require the user ID to
# appear in the DN.
# 选择用来认证的用户DN中用户节点的映射方式。
#
ldap.authentication.userNameFormat=cn=%s,ou=users,ou=system
# The LDAP context factory to use
# LDAP环境使用的factory类名称,一般的符合Open LDAP标准的服务器都不需要修改此设置。
#
ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
# The URL to connect to the LDAP server
# LDAP服务器地址
ldap.authentication.java.naming.provider.url=ldap://station1:10389
# The authentication mechanism to use
# 连接到LDAP服务器的认证方式,可以是simple, DIGEST MD5 or GSSAPI等等。这里我们使用简单认证
ldap.authentication.java.naming.security.authentication=simple
# Escape commas entered by the user at bind time
# Useful when using simple authentication and the CN is part of the DN and contains commas
ldap.authentication.escapeCommasInBind=false
# Escape commas entered by the user when setting the authenticated user
# Useful when using simple authentication and the CN is part of the DN and contains commas, and the escaped \, is
# pulled in as part of an LDAP sync
# If this option is set to true it will break the default home folder provider as space names can not contain \
ldap.authentication.escapeCommasInUid=false
# Comma separated list of user names who should be considered administrators by default
# 前面提到过的,系统的管理员用户,可以是多个,用逗号分隔。这个用户将获得登录你alfresco的管理员后台的权限。必须是你LDAP目录结构中存在的用户。
#
ldap.authentication.defaultAdministratorUserNames=admin
# This flag enables use of this LDAP subsystem for user and group
# synchronization. It may be that this subsytem should only be used for
# authentication, in which case this flag should be set to false.
# 是否开启同步,如果LDAP中存在alfresco系统数据库中不存在的用户,将自动同步。反向不适用。
#
ldap.synchronization.active=true
# The default principal to use (only used for LDAP sync)
# 用来同步使用的LDAP服务器管理员帐号
#
ldap.synchronization.java.naming.security.principal=uid=admin,ou=system
# The password for the default principal (only used for LDAP sync)
# 上面指定的管理员帐号的密码
#
ldap.synchronization.java.naming.security.credentials=secret
# If positive, this property indicates that RFC 2696 paged results should be
# used to split query results into batches of the specified size. This
# overcomes any size limits imposed by the LDAP server.
ldap.synchronization.queryBatchSize=0
# If positive, this property indicates that range retrieval should be used to fetch
# multi-valued attributes (such as member) in batches of the specified size.
# Overcomes any size limits imposed by Active Directory.
ldap.synchronization.attributeBatchSize=0
# The query to select all objects that represent the groups to import.
# 设定查询组的时候选取的类型
#
ldap.synchronization.groupQuery=(objectclass\=groupOfNames)
# The query to select objects that represent the groups to import that have changed since a certain time.
# 查询时针对作出改动的节点同步使用的表达式(下同)
#
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=groupOfNames)(!(modifyTimestamp< \={0})))
# The query to select all objects that represent the users to import.
# 设定查询用户的时候选取的类型
ldap.synchronization.personQuery=(objectclass\=inetOrgPerson)
# The query to select objects that represent the users to import that have changed since a certain time.
ldap.synchronization.personDifferentialQuery=(&(objectclass\=inetOrgPerson)(!(modifyTimestamp<\={0})))
# The group search base restricts the LDAP group query to a sub section of tree on the LDAP server.
# 用户组信息的位置
#
ldap.synchronization.groupSearchBase=ou\=groups,ou\=system
# The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
# 用户信息位置
#
ldap.synchronization.userSearchBase=ou\=users,ou\=system
# The name of the operational attribute recording the last update time for a group or user.
ldap.synchronization.modifyTimestampAttributeName=modifyTimestamp
# The timestamp format. Unfortunately, this varies between directory servers.
ldap.synchronization.timestampFormat=yyyyMMddHHmmss'Z'
# The attribute name on people objects found in LDAP to use as the uid in Alfresco
ldap.synchronization.userIdAttributeName=cn
# The attribute on person objects in LDAP to map to the first name property in Alfresco
ldap.synchronization.userFirstNameAttributeName=givenName
# The attribute on person objects in LDAP to map to the last name property in Alfresco
ldap.synchronization.userLastNameAttributeName=sn
# The attribute on person objects in LDAP to map to the email property in Alfresco
ldap.synchronization.userEmailAttributeName=mail
# The attribute on person objects in LDAP to map to the organizational id property in Alfresco
ldap.synchronization.userOrganizationalIdAttributeName=o
# The default home folder provider to use for people created via LDAP import
# 同步发生后,新用户第一次登陆时使用的默认目录创建器。注意请保证这里选择的创建器正常工作,否则可能会导致同步后的用户无法正常登录。
# 几种HomeFolderProvider的使用请参看 http://wiki.alfresco.com/wiki/Security_Services#Providers
#
ldap.synchronization.defaultHomeFolderProvider=userHomesHomeFolderProvider
# The attribute on LDAP group objects to map to the gid property in Alfrecso
ldap.synchronization.groupIdAttributeName=cn
# The group type in LDAP
ldap.synchronization.groupType=groupOfNames
# The person type in LDAP
ldap.synchronization.personType=inetOrgPerson
# The attribute in LDAP on group objects that defines the DN for its members
ldap.synchronization.groupMemberAttributeName=member
# If true progress estimation is enabled. When enabled, the user query has to be run twice in order to count entries.
ldap.synchronization.enableProgressEstimation=true
如果前面使用和我这里一样的LDAP目录结构,直接使用我这里提供的properties文件,对服务器地址,端口,管理员用户名和密码做出修改即可。该Properties文件的详细介绍,参看官方WIKI中的LDAP Authentication章节。
测试结果
配置部分到这里就结束了,现在可以来启动alfresco进行测试。注意观察log,如果在:
Loading properties file from class path resource [alfresco/alfresco-shared.properties]
之后出现:
18:28:31,791 INFO [org.alfresco.config.JndiPropertiesFactoryBean] Loading properties file from file [C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension\subsystems\Authentication\ldap\myldap\ldap-synchronisation.properties]
表示你在alfresco全局设置文件(alfresco-global.properties)中作出的authentication.chain改动已生效,并且系统已经正确的找到了相应的properties文件的位置。
如果properties文件的设置正确的话,之后会看到:
[org.alfresco.repo.management.subsystems.ChildApplicationContextFactory] Starting 'Authentication' subsystem, ID: [Authentication, managed, myldap]
以及一些同步用户数据的过程和结果:
18:28:52,395 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Synchronizing users and groups with user registry 'myldap' 18:28:52,399 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Retrieving all groups from user registry 'myldap' 18:28:52,458 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Analysis: Commencing batch of 2 entries 18:28:52,501 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Analysis: Processed 2 entries out of 2. 100% complete. Rate: 46 per second. 0 failures detected. 18:28:52,502 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Analysis: Completed batch of 2 entries 18:28:52,520 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Creation and Association: Commencing batch of 2 entries 18:28:52,907 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Creation and Association: Processed 2 entries out of 2. 100% complete. Rate: 5 per second. 0 failures detected. 18:28:52,908 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap Group Creation and Association: Completed batch of 2 entries 18:28:52,912 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Retrieving all users from user registry 'myldap' 18:28:52,923 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap User Creation and Association: Commencing batch of 3 entries 18:28:53,737 WARN [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Updating user 'admin'. This user will in future be assumed to originate from user registry 'myldap'. 18:28:54,086 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap User Creation and Association: Processed 3 entries out of 3. 100% complete. Rate: 2 per second. 0 failures detected. 18:28:54,086 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] myldap User Creation and Association: Completed batch of 3 entries 18:28:54,238 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Finished synchronizing users and groups with user registry 'myldap' 18:28:54,238 INFO [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] 3 user(s) and 2 group(s) processed
最后会出现:
18:28:54,280 INFO [org.alfresco.repo.management.subsystems.ChildApplicationContextFactory] Startup of 'Synchronization' subsystem, ID: [Synchronization, default] complete
表示同步已成功的完成。开启浏览器打开alfresco的网络界面。http://localhost:8080/alfresco,使用我们在LDAP中设置的用户Admin登录,成功登录后可以进入管理员界面,在后台中查看用户信息,只有admin用户。 使用我们创建的另外一个用户samuel同样成功登录,但只具备普通用户权限,在log窗口中会看到该用户在登录的瞬间被同步到alfresco内置用户数据表中,并且系统会为其在自动创建一个和用户名同名的home folder。
如果你的log或者tomcat窗口中看不到我上面说的这些log信息,修改alfresco的log4j properties文件。
%Alfresco_home%\tomcat\webapps\alfresco\WEB-INF\classes\log4j.properties
增加:
log4j.logger.org.alfresco.repo.security.sync=debug
这可以按照我前面列出的ldif文件格式编写一个新LDAP用户文件,实时导入到LDAP服务器中,然后不重启alfresco,使用该用户登录。如果上面设置一切正确,会看到该用户一样被同步到alfresco的内置数据库中。至此,我们需要的功能实现。
更多
有其他问题的朋友可以到:
- alfresco官方论坛 - http://forums.alfresco.com/en/
- alfresco wiki - http://wiki.alfresco.com/wiki/Main_Page
寻找答案。
Reference:
- Alfresco 3 Enterprise Content Management Implementation (Paperback) by Munwar Shariff, Amita Bhandari, Vinita Choudhary, and Pallika Majumdar
- Alfresco Developer Guide by Jeff Potts (Paperback)
- Installing and Configuring Alfresco Community Edition 3.2r2
- Liferay, Alfresco, LDAP and SSO - Full Integration By Jonas Yuan




