mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
ETHREEOH-2242: New ldap-ad Authentication subsystem with defaults for Active Directory
- Fixed parsing of timestamps - Fixed resolution of group members - Shared Spring configuration with ldap subsystem - Authentication still only supported with DIGEST-MD5 binding enabled - chain with passthru authentication otherwise git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14934 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,354 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<!--
|
||||||
|
Bean definitions shared by the ldap and ldap-ad subsystems
|
||||||
|
-->
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
<!--
|
||||||
|
DAO that rejects changes - LDAP is read only at the moment. It does allow users to be deleted with out warnings
|
||||||
|
from the UI.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<bean id="authenticationDao" class="org.alfresco.repo.security.authentication.DefaultMutableAuthenticationDao">
|
||||||
|
<property name="allowSetEnabled" value="true" />
|
||||||
|
<property name="allowGetEnabled" value="true" />
|
||||||
|
<property name="allowDeleteUser" value="true" />
|
||||||
|
<property name="allowCreateUser" value="true" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- LDAP authentication configuration -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
You can also use JAAS authentication for Kerberos against Active Directory or NTLM if you also require single sign
|
||||||
|
on from the web browser. You do not have to use LDAP authentication to synchronise groups and users from an LDAP
|
||||||
|
store if it supports other authentication routes, like Active Directory.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<bean id="authenticationComponent" class="org.alfresco.repo.security.authentication.ldap.LDAPAuthenticationComponentImpl"
|
||||||
|
parent="authenticationComponentBase">
|
||||||
|
<property name="active">
|
||||||
|
<value>${ldap.authentication.active}</value>
|
||||||
|
</property>
|
||||||
|
<property name="LDAPInitialDirContextFactory">
|
||||||
|
<ref bean="ldapInitialDirContextFactory" />
|
||||||
|
</property>
|
||||||
|
<property name="userNameFormat">
|
||||||
|
<!--
|
||||||
|
|
||||||
|
This maps between what the user types in and what is passed through to the underlying LDAP authentication.
|
||||||
|
|
||||||
|
"%s" - the user id is passed through without modification. Used for LDAP authentication such as DIGEST-MD5,
|
||||||
|
anything that is not "simple". "cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the
|
||||||
|
authenticate as "cn=Joe Bloggs,ou=London,dc=company,dc=com" Usually for simple authentication. Simple
|
||||||
|
authentication always uses the DN for the user.
|
||||||
|
-->
|
||||||
|
<value>${ldap.authentication.userNameFormat}</value>
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="transactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="escapeCommasInBind">
|
||||||
|
<value>${ldap.authentication.escapeCommasInBind}</value>
|
||||||
|
</property>
|
||||||
|
<property name="escapeCommasInUid">
|
||||||
|
<value>${ldap.authentication.escapeCommasInUid}</value>
|
||||||
|
</property>
|
||||||
|
<property name="allowGuestLogin">
|
||||||
|
<value>${ldap.authentication.allowGuestLogin}</value>
|
||||||
|
</property>
|
||||||
|
<property name="defaultAdministratorUserNameList">
|
||||||
|
<value>${ldap.authentication.defaultAdministratorUserNames}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Wrapped version to be used within subsystem -->
|
||||||
|
<bean id="AuthenticationComponent" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||||
|
<property name="proxyInterfaces">
|
||||||
|
<value>org.alfresco.repo.security.authentication.AuthenticationComponent</value>
|
||||||
|
</property>
|
||||||
|
<property name="transactionManager">
|
||||||
|
<ref bean="transactionManager" />
|
||||||
|
</property>
|
||||||
|
<property name="target">
|
||||||
|
<ref bean="authenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionAttributes">
|
||||||
|
<props>
|
||||||
|
<prop key="*">${server.transaction.mode.default}</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Authenticaton service for chaining -->
|
||||||
|
<bean id="localAuthenticationService" class="org.alfresco.repo.security.authentication.AuthenticationServiceImpl">
|
||||||
|
<property name="authenticationDao">
|
||||||
|
<ref bean="authenticationDao" />
|
||||||
|
</property>
|
||||||
|
<property name="ticketComponent">
|
||||||
|
<ref bean="ticketComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="authenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="sysAdminCache">
|
||||||
|
<ref bean="sysAdminCache" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
This bean is used to support general LDAP authentication. It is also used to provide read only access to users and
|
||||||
|
groups to pull them out of the LDAP reopsitory
|
||||||
|
-->
|
||||||
|
|
||||||
|
<bean id="ldapInitialDirContextFactory" class="org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactoryImpl">
|
||||||
|
<property name="initialDirContextEnvironment">
|
||||||
|
<map>
|
||||||
|
<!-- The LDAP provider -->
|
||||||
|
<entry key="java.naming.factory.initial">
|
||||||
|
<value>${ldap.authentication.java.naming.factory.initial}</value>
|
||||||
|
</entry>
|
||||||
|
|
||||||
|
<!-- The url to the LDAP server -->
|
||||||
|
<!-- Note you can use space separated urls - they will be tried in turn until one works -->
|
||||||
|
<!-- This could be used to authenticate against one or more ldap servers (you will not know which one ....) -->
|
||||||
|
<entry key="java.naming.provider.url">
|
||||||
|
<value>${ldap.authentication.java.naming.provider.url}</value>
|
||||||
|
</entry>
|
||||||
|
|
||||||
|
<!-- The authentication mechanism to use -->
|
||||||
|
<!-- Some sasl authentication mechanisms may require a realm to be set -->
|
||||||
|
<!-- java.naming.security.sasl.realm -->
|
||||||
|
<!-- The available options will depend on your LDAP provider -->
|
||||||
|
<entry key="java.naming.security.authentication">
|
||||||
|
<value>${ldap.authentication.java.naming.security.authentication}</value>
|
||||||
|
</entry>
|
||||||
|
|
||||||
|
<!-- The id of a user who can read group and user information -->
|
||||||
|
<!-- This does not go through the pattern substitution defined above and is used "as is" -->
|
||||||
|
<entry key="java.naming.security.principal">
|
||||||
|
<value>${ldap.synchronization.java.naming.security.principal}</value>
|
||||||
|
</entry>
|
||||||
|
|
||||||
|
<!-- The password for the user defined above -->
|
||||||
|
<entry key="java.naming.security.credentials">
|
||||||
|
<value>${ldap.synchronization.java.naming.security.credentials}</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Regularly exports user and group information from LDAP -->
|
||||||
|
|
||||||
|
<bean id="userRegistry" class="org.alfresco.repo.security.sync.ldap.LDAPUserRegistry">
|
||||||
|
<property name="active">
|
||||||
|
<value>${ldap.synchronization.active}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<property name="queryBatchSize">
|
||||||
|
<value>${ldap.synchronization.queryBatchSize}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The query to select all objects that represent the groups to import.
|
||||||
|
|
||||||
|
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||||
|
(objectclass=groupOfNames)
|
||||||
|
|
||||||
|
For Active Directory:
|
||||||
|
(objectclass=group)
|
||||||
|
-->
|
||||||
|
<property name="groupQuery">
|
||||||
|
<value>${ldap.synchronization.groupQuery}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The query to select objects that represent the groups to import that have changed since a certain time.
|
||||||
|
|
||||||
|
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||||
|
(&(objectclass=groupOfNames)(!(modifyTimestamp<={0})))
|
||||||
|
|
||||||
|
For Active Directory:
|
||||||
|
(&(objectclass=group)(!(modifyTimestamp<={0})))
|
||||||
|
-->
|
||||||
|
<property name="groupDifferentialQuery">
|
||||||
|
<value>${ldap.synchronization.groupDifferentialQuery}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The query to select all objects that represent the users to import.
|
||||||
|
|
||||||
|
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||||
|
(objectclass=inetOrgPerson)
|
||||||
|
|
||||||
|
For Active Directory:
|
||||||
|
(objectclass=user)
|
||||||
|
-->
|
||||||
|
<property name="personQuery">
|
||||||
|
<value>${ldap.synchronization.personQuery}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The query to select objects that represent the users to import that have changed since a certain time.
|
||||||
|
|
||||||
|
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||||
|
(&(objectclass=inetOrgPerson)(!(modifyTimestamp<={0})))
|
||||||
|
|
||||||
|
For Active Directory:
|
||||||
|
(&(objectclass=user)(!(modifyTimestamp<={0})))
|
||||||
|
-->
|
||||||
|
<property name="personDifferentialQuery">
|
||||||
|
<value>${ldap.synchronization.personDifferentialQuery}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The group search base restricts the LDAP group query to a sub section of tree on the LDAP server.
|
||||||
|
-->
|
||||||
|
<property name="groupSearchBase">
|
||||||
|
<value>${ldap.synchronization.groupSearchBase}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
|
||||||
|
-->
|
||||||
|
<property name="userSearchBase">
|
||||||
|
<value>${ldap.synchronization.userSearchBase}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The unique identifier for the user.
|
||||||
|
-->
|
||||||
|
<property name="userIdAttributeName">
|
||||||
|
<value>${ldap.synchronization.userIdAttributeName}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The name of the operational attribute recording the last update time for a group or user.
|
||||||
|
-->
|
||||||
|
<property name="modifyTimestampAttributeName">
|
||||||
|
<value>${ldap.synchronization.modifyTimestampAttributeName}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The timestamp format. Unfortunately, this varies between directory servers.
|
||||||
|
-->
|
||||||
|
<property name="timestampFormat">
|
||||||
|
<value>${ldap.synchronization.timestampFormat}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
An attribute that is a unique identifier for each group found.
|
||||||
|
This is also the name of the group with the current group implementation.
|
||||||
|
This is mandatory for any groups found.
|
||||||
|
|
||||||
|
OpenLDAP: "cn" as it is mandatory on groupOfNames
|
||||||
|
Active Directory: "cn"
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property name="groupIdAttributeName">
|
||||||
|
<value>${ldap.synchronization.groupIdAttributeName}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The objectClass attribute for group members.
|
||||||
|
For each member of a group, the distinguished name is given.
|
||||||
|
The object is looked up by its DN. If the object is of this class it is treated as a group.
|
||||||
|
-->
|
||||||
|
<property name="groupType">
|
||||||
|
<value>${ldap.synchronization.groupType}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The objectClass attribute for person members.
|
||||||
|
For each member of a group, the distinguished name is given.
|
||||||
|
The object is looked up by its DN. If the object is of this class it is treated as a person.
|
||||||
|
-->
|
||||||
|
<property name="personType">
|
||||||
|
<value>${ldap.synchronization.personType}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The repeating attribute on group objects (found by query or as sub groups)
|
||||||
|
used to define membership of the group. This is assumed to hold distinguished names of
|
||||||
|
other groups or users/people; the above types are used to determine this.
|
||||||
|
|
||||||
|
OpenLDAP: "member" as it is mandatory on groupOfNames
|
||||||
|
Active Directory: "member"
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property name="memberAttribute">
|
||||||
|
<value>${ldap.synchronization.groupMemberAttributeName}</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This property defines a mapping between attributes held on LDAP user objects and
|
||||||
|
the properties of user objects held in the repository. The key is the QName of an attribute in
|
||||||
|
the repository, the value is the attribute name from the user/inetOrgPerson/.. object in the
|
||||||
|
LDAP repository.
|
||||||
|
-->
|
||||||
|
<property name="attributeMapping">
|
||||||
|
<map>
|
||||||
|
<entry key="cm:userName">
|
||||||
|
<!-- Must match the same attribute as userIdAttributeName -->
|
||||||
|
<value>${ldap.synchronization.userIdAttributeName}</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="cm:firstName">
|
||||||
|
<!-- OpenLDAP: "givenName" -->
|
||||||
|
<!-- Active Directory: "givenName" -->
|
||||||
|
<value>${ldap.synchronization.userFirstNameAttributeName}</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="cm:lastName">
|
||||||
|
<!-- OpenLDAP: "sn" -->
|
||||||
|
<!-- Active Directory: "sn" -->
|
||||||
|
<value>${ldap.synchronization.userLastNameAttributeName}</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="cm:email">
|
||||||
|
<!-- OpenLDAP: "mail" -->
|
||||||
|
<!-- Active Directory: "???" -->
|
||||||
|
<value>${ldap.synchronization.userEmailAttributeName}</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="cm:organizationId">
|
||||||
|
<!-- OpenLDAP: "o" -->
|
||||||
|
<!-- Active Directory: "???" -->
|
||||||
|
<value>${ldap.synchronization.userOrganizationalIdAttributeName}</value>
|
||||||
|
</entry>
|
||||||
|
<!-- Always use the default -->
|
||||||
|
<entry key="cm:homeFolderProvider">
|
||||||
|
<null/>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
<!-- Set a default home folder provider -->
|
||||||
|
<!-- Defaults only apply for values above -->
|
||||||
|
<property name="attributeDefaults">
|
||||||
|
<map>
|
||||||
|
<entry key="cm:homeFolderProvider">
|
||||||
|
<value>${ldap.synchronization.defaultHomeFolderProvider}</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!-- Services -->
|
||||||
|
<property name="LDAPInitialDirContextFactory">
|
||||||
|
<ref bean="ldapInitialDirContextFactory"/>
|
||||||
|
</property>
|
||||||
|
<property name="namespaceService">
|
||||||
|
<ref bean="namespaceService"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
<!--
|
||||||
|
The bean definitions for this subsystem are shared by the ldap and ldap-ad subsystems with different property
|
||||||
|
defaults
|
||||||
|
-->
|
||||||
|
<import resource="../common-ldap-context.xml" />
|
||||||
|
</beans>
|
@@ -0,0 +1,109 @@
|
|||||||
|
# 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.authentication.active=true
|
||||||
|
|
||||||
|
#
|
||||||
|
# This properties file brings together the common options for LDAP authentication rather than editing the bean definitions
|
||||||
|
#
|
||||||
|
ldap.authentication.allowGuestLogin=true
|
||||||
|
# How to map the user id entered by the user to taht 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
|
||||||
|
ldap.authentication.userNameFormat=%s
|
||||||
|
|
||||||
|
# The LDAP context factory to use
|
||||||
|
ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
|
||||||
|
|
||||||
|
# The URL to connect to the LDAP server
|
||||||
|
ldap.authentication.java.naming.provider.url=ldap://domaincontroller.company.com:389
|
||||||
|
|
||||||
|
# The authentication mechanism to use
|
||||||
|
ldap.authentication.java.naming.security.authentication=DIGEST-MD5
|
||||||
|
|
||||||
|
# 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
|
||||||
|
ldap.authentication.defaultAdministratorUserNames=Administrator
|
||||||
|
|
||||||
|
# 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.synchronization.active=true
|
||||||
|
|
||||||
|
# The default principal to use (only used for LDAP sync)
|
||||||
|
ldap.synchronization.java.naming.security.principal=alfresco
|
||||||
|
|
||||||
|
# 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=1000
|
||||||
|
|
||||||
|
# The query to select all objects that represent the groups to import.
|
||||||
|
ldap.synchronization.groupQuery=(objectclass\=group)
|
||||||
|
|
||||||
|
# The query to select objects that represent the groups to import that have changed since a certain time.
|
||||||
|
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(!(modifyTimestamp<\={0})))
|
||||||
|
|
||||||
|
# The query to select all objects that represent the users to import.
|
||||||
|
ldap.synchronization.personQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512))
|
||||||
|
|
||||||
|
# The query to select objects that represent the users to import that have changed since a certain time.
|
||||||
|
ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(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\=Security Groups,ou\=Alfresco,dc=domain
|
||||||
|
|
||||||
|
# The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
|
||||||
|
ldap.synchronization.userSearchBase=ou\=User Accounts,ou=\Alfresco,dc=domain
|
||||||
|
|
||||||
|
# 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'.0Z'
|
||||||
|
|
||||||
|
# The attribute name on people objects found in LDAP to use as the uid in Alfresco
|
||||||
|
ldap.synchronization.userIdAttributeName=sAMAccountName
|
||||||
|
|
||||||
|
# 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=company
|
||||||
|
|
||||||
|
# The default home folder provider to use for people created via LDAP import
|
||||||
|
ldap.synchronization.defaultHomeFolderProvider=personalHomeFolderProvider
|
||||||
|
|
||||||
|
# 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=group
|
||||||
|
|
||||||
|
# The person type in LDAP
|
||||||
|
ldap.synchronization.personType=user
|
||||||
|
|
||||||
|
# The attribute in LDAP on group objects that defines the DN for its members
|
||||||
|
ldap.synchronization.groupMemberAttributeName=member
|
@@ -3,342 +3,8 @@
|
|||||||
|
|
||||||
<beans>
|
<beans>
|
||||||
<!--
|
<!--
|
||||||
DAO that rejects changes - LDAP is read only at the moment. It does allow users to be deleted with out warnings
|
The bean definitions for this subsystem are shared by the ldap and ldap-ad subsystems with different property
|
||||||
from the UI.
|
defaults
|
||||||
-->
|
-->
|
||||||
|
<import resource="../common-ldap-context.xml" />
|
||||||
<bean id="authenticationDao" class="org.alfresco.repo.security.authentication.DefaultMutableAuthenticationDao">
|
|
||||||
<property name="allowSetEnabled" value="true" />
|
|
||||||
<property name="allowGetEnabled" value="true" />
|
|
||||||
<property name="allowDeleteUser" value="true" />
|
|
||||||
<property name="allowCreateUser" value="true" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- LDAP authentication configuration -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
You can also use JAAS authentication for Kerberos against Active Directory or NTLM if you also require single sign
|
|
||||||
on from the web browser. You do not have to use LDAP authentication to synchronise groups and users from an LDAP
|
|
||||||
store if it supports other authentication routes, like Active Directory.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<bean id="authenticationComponent" class="org.alfresco.repo.security.authentication.ldap.LDAPAuthenticationComponentImpl"
|
|
||||||
parent="authenticationComponentBase">
|
|
||||||
<property name="active">
|
|
||||||
<value>${ldap.authentication.active}</value>
|
|
||||||
</property>
|
|
||||||
<property name="LDAPInitialDirContextFactory">
|
|
||||||
<ref bean="ldapInitialDirContextFactory" />
|
|
||||||
</property>
|
|
||||||
<property name="userNameFormat">
|
|
||||||
<!--
|
|
||||||
|
|
||||||
This maps between what the user types in and what is passed through to the underlying LDAP authentication.
|
|
||||||
|
|
||||||
"%s" - the user id is passed through without modification. Used for LDAP authentication such as DIGEST-MD5,
|
|
||||||
anything that is not "simple". "cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the
|
|
||||||
authenticate as "cn=Joe Bloggs,ou=London,dc=company,dc=com" Usually for simple authentication. Simple
|
|
||||||
authentication always uses the DN for the user.
|
|
||||||
-->
|
|
||||||
<value>${ldap.authentication.userNameFormat}</value>
|
|
||||||
</property>
|
|
||||||
<property name="nodeService">
|
|
||||||
<ref bean="nodeService" />
|
|
||||||
</property>
|
|
||||||
<property name="personService">
|
|
||||||
<ref bean="personService" />
|
|
||||||
</property>
|
|
||||||
<property name="transactionService">
|
|
||||||
<ref bean="transactionService" />
|
|
||||||
</property>
|
|
||||||
<property name="escapeCommasInBind">
|
|
||||||
<value>${ldap.authentication.escapeCommasInBind}</value>
|
|
||||||
</property>
|
|
||||||
<property name="escapeCommasInUid">
|
|
||||||
<value>${ldap.authentication.escapeCommasInUid}</value>
|
|
||||||
</property>
|
|
||||||
<property name="allowGuestLogin">
|
|
||||||
<value>${ldap.authentication.allowGuestLogin}</value>
|
|
||||||
</property>
|
|
||||||
<property name="defaultAdministratorUserNameList">
|
|
||||||
<value>${ldap.authentication.defaultAdministratorUserNames}</value>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- Wrapped version to be used within subsystem -->
|
|
||||||
<bean id="AuthenticationComponent" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
|
||||||
<property name="proxyInterfaces">
|
|
||||||
<value>org.alfresco.repo.security.authentication.AuthenticationComponent</value>
|
|
||||||
</property>
|
|
||||||
<property name="transactionManager">
|
|
||||||
<ref bean="transactionManager" />
|
|
||||||
</property>
|
|
||||||
<property name="target">
|
|
||||||
<ref bean="authenticationComponent" />
|
|
||||||
</property>
|
|
||||||
<property name="transactionAttributes">
|
|
||||||
<props>
|
|
||||||
<prop key="*">${server.transaction.mode.default}</prop>
|
|
||||||
</props>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- Authenticaton service for chaining -->
|
|
||||||
<bean id="localAuthenticationService" class="org.alfresco.repo.security.authentication.AuthenticationServiceImpl">
|
|
||||||
<property name="authenticationDao">
|
|
||||||
<ref bean="authenticationDao" />
|
|
||||||
</property>
|
|
||||||
<property name="ticketComponent">
|
|
||||||
<ref bean="ticketComponent" />
|
|
||||||
</property>
|
|
||||||
<property name="authenticationComponent">
|
|
||||||
<ref bean="authenticationComponent" />
|
|
||||||
</property>
|
|
||||||
<property name="sysAdminCache">
|
|
||||||
<ref bean="sysAdminCache" />
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
This bean is used to support general LDAP authentication. It is also used to provide read only access to users and
|
|
||||||
groups to pull them out of the LDAP reopsitory
|
|
||||||
-->
|
|
||||||
|
|
||||||
<bean id="ldapInitialDirContextFactory" class="org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactoryImpl">
|
|
||||||
<property name="initialDirContextEnvironment">
|
|
||||||
<map>
|
|
||||||
<!-- The LDAP provider -->
|
|
||||||
<entry key="java.naming.factory.initial">
|
|
||||||
<value>${ldap.authentication.java.naming.factory.initial}</value>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<!-- The url to the LDAP server -->
|
|
||||||
<!-- Note you can use space separated urls - they will be tried in turn until one works -->
|
|
||||||
<!-- This could be used to authenticate against one or more ldap servers (you will not know which one ....) -->
|
|
||||||
<entry key="java.naming.provider.url">
|
|
||||||
<value>${ldap.authentication.java.naming.provider.url}</value>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<!-- The authentication mechanism to use -->
|
|
||||||
<!-- Some sasl authentication mechanisms may require a realm to be set -->
|
|
||||||
<!-- java.naming.security.sasl.realm -->
|
|
||||||
<!-- The available options will depend on your LDAP provider -->
|
|
||||||
<entry key="java.naming.security.authentication">
|
|
||||||
<value>${ldap.authentication.java.naming.security.authentication}</value>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<!-- The id of a user who can read group and user information -->
|
|
||||||
<!-- This does not go through the pattern substitution defined above and is used "as is" -->
|
|
||||||
<entry key="java.naming.security.principal">
|
|
||||||
<value>${ldap.authentication.java.naming.security.principal}</value>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<!-- The password for the user defined above -->
|
|
||||||
<entry key="java.naming.security.credentials">
|
|
||||||
<value>${ldap.authentication.java.naming.security.credentials}</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- Regularly exports user and group information from LDAP -->
|
|
||||||
|
|
||||||
<bean id="userRegistry" class="org.alfresco.repo.security.sync.ldap.LDAPUserRegistry">
|
|
||||||
<property name="active">
|
|
||||||
<value>${ldap.synchronization.active}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<property name="queryBatchSize">
|
|
||||||
<value>${ldap.synchronization.queryBatchSize}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The query to select all objects that represent the groups to import.
|
|
||||||
|
|
||||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
|
||||||
(objectclass=groupOfNames)
|
|
||||||
|
|
||||||
For Active Directory:
|
|
||||||
(objectclass=group)
|
|
||||||
-->
|
|
||||||
<property name="groupQuery">
|
|
||||||
<value>${ldap.synchronization.groupQuery}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The query to select objects that represent the groups to import that have changed since a certain time.
|
|
||||||
|
|
||||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
|
||||||
(&(objectclass=groupOfNames)(!(modifyTimestamp<={0})))
|
|
||||||
|
|
||||||
For Active Directory:
|
|
||||||
(&(objectclass=group)(!(modifyTimestamp<={0})))
|
|
||||||
-->
|
|
||||||
<property name="groupDifferentialQuery">
|
|
||||||
<value>${ldap.synchronization.groupDifferentialQuery}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The query to select all objects that represent the users to import.
|
|
||||||
|
|
||||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
|
||||||
(objectclass=inetOrgPerson)
|
|
||||||
|
|
||||||
For Active Directory:
|
|
||||||
(objectclass=user)
|
|
||||||
-->
|
|
||||||
<property name="personQuery">
|
|
||||||
<value>${ldap.synchronization.personQuery}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The query to select objects that represent the users to import that have changed since a certain time.
|
|
||||||
|
|
||||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
|
||||||
(&(objectclass=inetOrgPerson)(!(modifyTimestamp<={0})))
|
|
||||||
|
|
||||||
For Active Directory:
|
|
||||||
(&(objectclass=user)(!(modifyTimestamp<={0})))
|
|
||||||
-->
|
|
||||||
<property name="personDifferentialQuery">
|
|
||||||
<value>${ldap.synchronization.personDifferentialQuery}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The group search base restricts the LDAP group query to a sub section of tree on the LDAP server.
|
|
||||||
-->
|
|
||||||
<property name="groupSearchBase">
|
|
||||||
<value>${ldap.synchronization.groupSearchBase}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
|
|
||||||
-->
|
|
||||||
<property name="userSearchBase">
|
|
||||||
<value>${ldap.synchronization.userSearchBase}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The unique identifier for the user.
|
|
||||||
-->
|
|
||||||
<property name="userIdAttributeName">
|
|
||||||
<value>${ldap.synchronization.userIdAttributeName}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The name of the operational attribute recording the last update time for a group or user.
|
|
||||||
-->
|
|
||||||
<property name="modifyTimestampAttributeName">
|
|
||||||
<value>${ldap.synchronization.modifyTimestampAttributeName}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
An attribute that is a unique identifier for each group found.
|
|
||||||
This is also the name of the group with the current group implementation.
|
|
||||||
This is mandatory for any groups found.
|
|
||||||
|
|
||||||
OpenLDAP: "cn" as it is mandatory on groupOfNames
|
|
||||||
Active Directory: "cn"
|
|
||||||
|
|
||||||
-->
|
|
||||||
<property name="groupIdAttributeName">
|
|
||||||
<value>${ldap.synchronization.groupIdAttributeName}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The objectClass attribute for group members.
|
|
||||||
For each member of a group, the distinguished name is given.
|
|
||||||
The object is looked up by its DN. If the object is of this class it is treated as a group.
|
|
||||||
-->
|
|
||||||
<property name="groupType">
|
|
||||||
<value>${ldap.synchronization.groupType}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The objectClass attribute for person members.
|
|
||||||
For each member of a group, the distinguished name is given.
|
|
||||||
The object is looked up by its DN. If the object is of this class it is treated as a person.
|
|
||||||
-->
|
|
||||||
<property name="personType">
|
|
||||||
<value>${ldap.synchronization.personType}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The repeating attribute on group objects (found by query or as sub groups)
|
|
||||||
used to define membership of the group. This is assumed to hold distinguished names of
|
|
||||||
other groups or users/people; the above types are used to determine this.
|
|
||||||
|
|
||||||
OpenLDAP: "member" as it is mandatory on groupOfNames
|
|
||||||
Active Directory: "member"
|
|
||||||
|
|
||||||
-->
|
|
||||||
<property name="memberAttribute">
|
|
||||||
<value>${ldap.synchronization.groupMemberAttributeName}</value>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
This property defines a mapping between attributes held on LDAP user objects and
|
|
||||||
the properties of user objects held in the repository. The key is the QName of an attribute in
|
|
||||||
the repository, the value is the attribute name from the user/inetOrgPerson/.. object in the
|
|
||||||
LDAP repository.
|
|
||||||
-->
|
|
||||||
<property name="attributeMapping">
|
|
||||||
<map>
|
|
||||||
<entry key="cm:userName">
|
|
||||||
<!-- Must match the same attribute as userIdAttributeName -->
|
|
||||||
<value>${ldap.synchronization.userIdAttributeName}</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="cm:firstName">
|
|
||||||
<!-- OpenLDAP: "givenName" -->
|
|
||||||
<!-- Active Directory: "givenName" -->
|
|
||||||
<value>${ldap.synchronization.userFirstNameAttributeName}</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="cm:lastName">
|
|
||||||
<!-- OpenLDAP: "sn" -->
|
|
||||||
<!-- Active Directory: "sn" -->
|
|
||||||
<value>${ldap.synchronization.userLastNameAttributeName}</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="cm:email">
|
|
||||||
<!-- OpenLDAP: "mail" -->
|
|
||||||
<!-- Active Directory: "???" -->
|
|
||||||
<value>${ldap.synchronization.userEmailAttributeName}</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="cm:organizationId">
|
|
||||||
<!-- OpenLDAP: "o" -->
|
|
||||||
<!-- Active Directory: "???" -->
|
|
||||||
<value>${ldap.synchronization.userOrganizationalIdAttributeName}</value>
|
|
||||||
</entry>
|
|
||||||
<!-- Always use the default -->
|
|
||||||
<entry key="cm:homeFolderProvider">
|
|
||||||
<null/>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</property>
|
|
||||||
<!-- Set a default home folder provider -->
|
|
||||||
<!-- Defaults only apply for values above -->
|
|
||||||
<property name="attributeDefaults">
|
|
||||||
<map>
|
|
||||||
<entry key="cm:homeFolderProvider">
|
|
||||||
<value>${ldap.synchronization.defaultHomeFolderProvider}</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!-- Services -->
|
|
||||||
<property name="LDAPInitialDirContextFactory">
|
|
||||||
<ref bean="ldapInitialDirContextFactory"/>
|
|
||||||
</property>
|
|
||||||
<property name="namespaceService">
|
|
||||||
<ref bean="namespaceService"/>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -25,12 +25,6 @@ ldap.authentication.java.naming.provider.url=ldap://openldap.domain.com:389
|
|||||||
# The authentication mechanism to use
|
# The authentication mechanism to use
|
||||||
ldap.authentication.java.naming.security.authentication=simple
|
ldap.authentication.java.naming.security.authentication=simple
|
||||||
|
|
||||||
# The default principal to use (only used for LDAP sync)
|
|
||||||
ldap.authentication.java.naming.security.principal=cn\=Manager,dc\=company,dc\=com
|
|
||||||
|
|
||||||
# The password for the default principal (only used for LDAP sync)
|
|
||||||
ldap.authentication.java.naming.security.credentials=secret
|
|
||||||
|
|
||||||
# Escape commas entered by the user at bind time
|
# 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
|
# Useful when using simple authentication and the CN is part of the DN and contains commas
|
||||||
ldap.authentication.escapeCommasInBind=false
|
ldap.authentication.escapeCommasInBind=false
|
||||||
@@ -49,6 +43,12 @@ ldap.authentication.defaultAdministratorUserNames=
|
|||||||
# authentication, in which case this flag should be set to false.
|
# authentication, in which case this flag should be set to false.
|
||||||
ldap.synchronization.active=true
|
ldap.synchronization.active=true
|
||||||
|
|
||||||
|
# The default principal to use (only used for LDAP sync)
|
||||||
|
ldap.synchronization.java.naming.security.principal=cn\=Manager,dc\=company,dc\=com
|
||||||
|
|
||||||
|
# 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
|
# If positive, this property indicates that RFC 2696 paged results should be
|
||||||
# used to split query results into batches of the specified size. This
|
# used to split query results into batches of the specified size. This
|
||||||
# overcomes any size limits imposed by the LDAP server.
|
# overcomes any size limits imposed by the LDAP server.
|
||||||
@@ -75,6 +75,9 @@ ldap.synchronization.userSearchBase=ou\=People,dc\=company,dc\=com
|
|||||||
# The name of the operational attribute recording the last update time for a group or user.
|
# The name of the operational attribute recording the last update time for a group or user.
|
||||||
ldap.synchronization.modifyTimestampAttributeName=modifyTimestamp
|
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
|
# The attribute name on people objects found in LDAP to use as the uid in Alfresco
|
||||||
ldap.synchronization.userIdAttributeName=uid
|
ldap.synchronization.userIdAttributeName=uid
|
||||||
|
|
||||||
|
@@ -145,11 +145,12 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
private String[] groupAttributeNames;
|
private String[] groupAttributeNames;
|
||||||
|
|
||||||
/** The LDAP generalized time format. */
|
/** The LDAP generalized time format. */
|
||||||
private static DateFormat LDAP_GENERALIZED_TIME_FORMAT;
|
private DateFormat timestampFormat;
|
||||||
static
|
|
||||||
|
public LDAPUserRegistry()
|
||||||
{
|
{
|
||||||
LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
|
// Default to official LDAP generalized time format (unfortunately not used by Active Directory)
|
||||||
LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
|
setTimestampFormat("yyyyMMddHHmmss'Z'");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,6 +296,22 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
this.modifyTimestampAttributeName = modifyTimestampAttributeName;
|
this.modifyTimestampAttributeName = modifyTimestampAttributeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the timestamp format. Unfortunately, this varies between directory servers.
|
||||||
|
*
|
||||||
|
* @param timestampFormat
|
||||||
|
* the timestamp format
|
||||||
|
* <ul>
|
||||||
|
* <li>OpenLDAP: "yyyyMMddHHmmss'Z'"
|
||||||
|
* <li>Active Directory: "yyyyMMddHHmmss'.0Z'"
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public void setTimestampFormat(String timestampFormat)
|
||||||
|
{
|
||||||
|
this.timestampFormat = new SimpleDateFormat(timestampFormat);
|
||||||
|
this.timestampFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decides whether to error on missing group members.
|
* Decides whether to error on missing group members.
|
||||||
*
|
*
|
||||||
@@ -464,12 +481,17 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
{
|
{
|
||||||
searchResults = ctx.search(this.groupSearchBase, this.groupDifferentialQuery, new Object[]
|
searchResults = ctx.search(this.groupSearchBase, this.groupDifferentialQuery, new Object[]
|
||||||
{
|
{
|
||||||
LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT.format(modifiedSince)
|
this.timestampFormat.format(modifiedSince)
|
||||||
}, userSearchCtls);
|
}, userSearchCtls);
|
||||||
}
|
}
|
||||||
|
|
||||||
LdapName groupDistinguishedNamePrefix = new LdapName(this.groupSearchBase);
|
LdapName groupDistinguishedNamePrefix = new LdapName(this.groupSearchBase);
|
||||||
LdapName userDistinguishedNamePrefix = new LdapName(this.userSearchBase);
|
LdapName userDistinguishedNamePrefix = new LdapName(this.userSearchBase);
|
||||||
|
|
||||||
|
// Work out whether the user and group trees are disjoint. This may allow us to optimize reverse DN
|
||||||
|
// resolution.
|
||||||
|
boolean disjoint = !groupDistinguishedNamePrefix.startsWith(userDistinguishedNamePrefix)
|
||||||
|
&& !userDistinguishedNamePrefix.startsWith(groupDistinguishedNamePrefix);
|
||||||
|
|
||||||
while (searchResults.hasMoreElements())
|
while (searchResults.hasMoreElements())
|
||||||
{
|
{
|
||||||
@@ -511,8 +533,7 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
Attribute modifyTimestamp = attributes.get(this.modifyTimestampAttributeName);
|
Attribute modifyTimestamp = attributes.get(this.modifyTimestampAttributeName);
|
||||||
if (modifyTimestamp != null)
|
if (modifyTimestamp != null)
|
||||||
{
|
{
|
||||||
group.setLastModified(LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT.parse(modifyTimestamp.get()
|
group.setLastModified(this.timestampFormat.parse(modifyTimestamp.get().toString()));
|
||||||
.toString()));
|
|
||||||
}
|
}
|
||||||
Set<String> childAssocs = group.getChildAssociations();
|
Set<String> childAssocs = group.getChildAssociations();
|
||||||
|
|
||||||
@@ -530,7 +551,7 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
|
|
||||||
// If the user and group search bases are different we may be able to recognise user and
|
// If the user and group search bases are different we may be able to recognise user and
|
||||||
// group DNs without a secondary lookup
|
// group DNs without a secondary lookup
|
||||||
if (!this.userSearchBase.equalsIgnoreCase(this.groupSearchBase))
|
if (disjoint)
|
||||||
{
|
{
|
||||||
Attributes nameAttributes = distinguishedName.getRdn(distinguishedName.size() - 1)
|
Attributes nameAttributes = distinguishedName.getRdn(distinguishedName.size() - 1)
|
||||||
.toAttributes();
|
.toAttributes();
|
||||||
@@ -563,8 +584,8 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
{
|
{
|
||||||
"objectclass", this.groupIdAttributeName, this.userIdAttributeName
|
"objectclass", this.groupIdAttributeName, this.userIdAttributeName
|
||||||
});
|
});
|
||||||
String objectclass = (String) childAttributes.get("objectclass").get();
|
Attribute objectClass = childAttributes.get("objectclass");
|
||||||
if (objectclass.equalsIgnoreCase(this.personType))
|
if (hasAttributeValue(objectClass, this.personType))
|
||||||
{
|
{
|
||||||
nameAttribute = childAttributes.get(this.userIdAttributeName);
|
nameAttribute = childAttributes.get(this.userIdAttributeName);
|
||||||
if (nameAttribute == null)
|
if (nameAttribute == null)
|
||||||
@@ -586,9 +607,8 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
childAssocs.add((String) nameAttribute.get());
|
childAssocs.add((String) nameAttribute.get());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (objectclass.equalsIgnoreCase(this.groupType))
|
else if (hasAttributeValue(objectClass, this.groupType))
|
||||||
{
|
{
|
||||||
|
|
||||||
nameAttribute = childAttributes.get(this.groupIdAttributeName);
|
nameAttribute = childAttributes.get(this.groupIdAttributeName);
|
||||||
if (nameAttribute == null)
|
if (nameAttribute == null)
|
||||||
{
|
{
|
||||||
@@ -656,6 +676,37 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does a case-insensitive search for the given value in an attribute
|
||||||
|
*
|
||||||
|
* @param attribute
|
||||||
|
* the attribute
|
||||||
|
* @param value
|
||||||
|
* the value to search for
|
||||||
|
* @return <code>true</code>, if the value was found
|
||||||
|
* @throws NamingException
|
||||||
|
* if there is a problem accessing the attribute values
|
||||||
|
*/
|
||||||
|
private boolean hasAttributeValue(Attribute attribute, String value) throws NamingException
|
||||||
|
{
|
||||||
|
NamingEnumeration<?> values = attribute.getAll();
|
||||||
|
while (values.hasMore())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value.equalsIgnoreCase((String) values.next()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ClassCastException e)
|
||||||
|
{
|
||||||
|
// Not a string value. ignore and continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps the LDAP user query as an {@link Iterator}.
|
* Wraps the LDAP user query as an {@link Iterator}.
|
||||||
*/
|
*/
|
||||||
@@ -811,8 +862,8 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
person.setLastModified(LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT.parse(modifyTimestamp
|
person.setLastModified(LDAPUserRegistry.this.timestampFormat.parse(modifyTimestamp.get()
|
||||||
.get().toString()));
|
.toString()));
|
||||||
}
|
}
|
||||||
catch (ParseException e)
|
catch (ParseException e)
|
||||||
{
|
{
|
||||||
@@ -879,7 +930,7 @@ public class LDAPUserRegistry implements UserRegistry, InitializingBean, Activat
|
|||||||
this.searchResults = this.ctx.search(LDAPUserRegistry.this.userSearchBase,
|
this.searchResults = this.ctx.search(LDAPUserRegistry.this.userSearchBase,
|
||||||
LDAPUserRegistry.this.personDifferentialQuery, new Object[]
|
LDAPUserRegistry.this.personDifferentialQuery, new Object[]
|
||||||
{
|
{
|
||||||
LDAPUserRegistry.LDAP_GENERALIZED_TIME_FORMAT.format(this.modifiedSince)
|
LDAPUserRegistry.this.timestampFormat.format(this.modifiedSince)
|
||||||
}, this.userSearchCtls);
|
}, this.userSearchCtls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user