我需要运行一个LDAP查询,该查询将在根查询中搜索两个特定的组织单位(OU),但是我很难解决它。我在下面尝试了以下查询,但都没有成功:
(|(OU=Staff,DC=my,DC=super,DC=org)(OU=Vendors,DC=my,DC=super,DC=org))
((OU=Staff,DC=my,DC=super,DC=org) | (OU=Vendors,DC=my,DC=super,DC=org))
我的问题是;是否可以在单个查询中查询多个单独的OU ?假设它是根LDAP查询中此类表达式的正确语法。
答案 0 :(得分:17)
你可以!!!简而言之,将此用作连接字符串:
ldap://<host>:3268/DC=<my>,DC=<domain>?cn
与您的搜索过滤器一起,例如
(&(sAMAccountName={0})(&((objectCategory=person)(objectclass=user)(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=<some-special-nested-group>,OU=<ou3>,OU=<ou2>,OU=<ou1>,DC=<dc3>,DC=<dc2>,DC=<dc1>))))
那将搜索所谓的Global Catalog,这在我们的环境中已经开箱即用。
而不是在我们的环境中不起作用的已知/常见其他版本(或其组合)与多个OU:
ldap://<host>/DC=<my>,DC=<domain>
ldap://<host>:389/DC=<my>,DC=<domain> (standard port)
ldap://<host>/OU=<someOU>,DC=<my>,DC=<domain>
ldap://<host>/CN=<someCN>,DC=<my>,DC=<domain>
ldap://<host>/(|(OU=<someOU1>)(OU=<someOU2>)),DC=<my>,DC=<domain> (search filters here shouldn't work at all by definition)
(我是开发人员,而不是AD / LDAP大师:)该死的我已经在各地寻找这个解决方案近两天而且几乎放弃了,习惯了我可能要实现这个明显非常常见的场景的想法手工(使用Jasperserver / Spring安全(/ Tomcat))。 (所以如果其他人或我将来再次遇到这个问题,这将是一个提醒:O))
我在研究过程中发现的一些其他相关主题几乎没什么帮助:
在这里,我将提供我们的匿名Tomcat LDAP配置,以防它可能有用
(/var/lib/tomcat7/webapps/jasperserver/WEB-INF/applicationContext-externalAUTH-LDAP.xml
):
<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-3.1.xsd">
<!-- ############ LDAP authentication ############ - Sample configuration
of external authentication via an external LDAP server. -->
<bean id="proxyAuthenticationProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.BaseAuthenticationProcessingFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer">
<ref local="externalDataSynchronizer" />
</property>
<property name="sessionRegistry">
<ref bean="sessionRegistry" />
</property>
<property name="internalAuthenticationFailureUrl" value="/login.html?error=1" />
<property name="defaultTargetUrl" value="/loginsuccess.html" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
</bean>
<bean id="proxyAuthenticationSoapProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.DefaultAuthenticationSoapProcessingFilter">
<property name="authenticationManager" ref="ldapAuthenticationManager" />
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
<property name="filterProcessesUrl" value="/services" />
</bean>
<bean id="proxyRequestParameterAuthenticationFilter"
class="com.jaspersoft.jasperserver.war.util.ExternalRequestParameterAuthenticationFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="authenticationFailureUrl">
<value>/login.html?error=1</value>
</property>
<property name="excludeUrls">
<list>
<value>/j_spring_switch_user</value>
</list>
</property>
</bean>
<bean id="proxyBasicProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ExternalAuthBasicProcessingFilter">
<property name="authenticationManager" ref="ldapAuthenticationManager" />
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="authenticationEntryPoint">
<ref local="basicProcessingFilterEntryPoint" />
</property>
</bean>
<bean id="proxyAuthenticationRestProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.DefaultAuthenticationRestProcessingFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer">
<ref local="externalDataSynchronizer" />
</property>
<property name="filterProcessesUrl" value="/rest/login" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
</bean>
<bean id="ldapAuthenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="ldapAuthenticationProvider" />
<ref bean="${bean.daoAuthenticationProvider}" />
<!--anonymousAuthenticationProvider only needed if filterInvocationInterceptor.alwaysReauthenticate
is set to true <ref bean="anonymousAuthenticationProvider"/> -->
</list>
</property>
</bean>
<bean id="ldapAuthenticationProvider"
class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<constructor-arg>
<bean
class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="ldapContextSource" />
</constructor-arg>
<property name="userSearch" ref="userSearch" />
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
<constructor-arg index="0">
<ref local="ldapContextSource" />
</constructor-arg>
<constructor-arg index="1">
<value></value>
</constructor-arg>
<property name="groupRoleAttribute" value="cn" />
<property name="convertToUpperCase" value="true" />
<property name="rolePrefix" value="ROLE_" />
<property name="groupSearchFilter"
value="(&(member={0})(&(objectCategory=Group)(objectclass=group)(cn=my-nested-group-name)))" />
<property name="searchSubtree" value="true" />
<!-- Can setup additional external default roles here <property name="defaultRole"
value="LDAP"/> -->
</bean>
</constructor-arg>
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0">
<value></value>
</constructor-arg>
<constructor-arg index="1">
<value>(&(sAMAccountName={0})(&((objectCategory=person)(objectclass=user)(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=my-nested-group-name,OU=ou3,OU=ou2,OU=ou1,DC=dc3,DC=dc2,DC=dc1))))
</value>
</constructor-arg>
<constructor-arg index="2">
<ref local="ldapContextSource" />
</constructor-arg>
<property name="searchSubtree">
<value>true</value>
</property>
</bean>
<bean id="ldapContextSource"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ldap.JSLdapContextSource">
<constructor-arg value="ldap://myhost:3268/DC=dc3,DC=dc2,DC=dc1?cn" />
<!-- manager user name and password (may not be needed) -->
<property name="userDn" value="CN=someuser,OU=ou4,OU=1,DC=dc3,DC=dc2,DC=dc1" />
<property name="password" value="somepass" />
<!--End Changes -->
</bean>
<!-- ############ LDAP authentication ############ -->
<!-- ############ JRS Synchronizer ############ -->
<bean id="externalDataSynchronizer"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ExternalDataSynchronizerImpl">
<property name="externalUserProcessors">
<list>
<ref local="externalUserSetupProcessor" />
<!-- Example processor for creating user folder -->
<!--<ref local="externalUserFolderProcessor"/> -->
</list>
</property>
</bean>
<bean id="abstractExternalProcessor"
class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.AbstractExternalUserProcessor"
abstract="true">
<property name="repositoryService" ref="${bean.repositoryService}" />
<property name="userAuthorityService" ref="${bean.userAuthorityService}" />
<property name="tenantService" ref="${bean.tenantService}" />
<property name="profileAttributeService" ref="profileAttributeService" />
<property name="objectPermissionService" ref="objectPermissionService" />
</bean>
<bean id="externalUserSetupProcessor"
class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.ExternalUserSetupProcessor"
parent="abstractExternalProcessor">
<property name="userAuthorityService">
<ref bean="${bean.internalUserAuthorityService}" />
</property>
<property name="defaultInternalRoles">
<list>
<value>ROLE_USER</value>
</list>
</property>
<property name="organizationRoleMap">
<map>
<!-- Example of mapping customer roles to JRS roles -->
<entry>
<key>
<value>ROLE_MY-NESTED-GROUP-NAME</value>
</key>
<!-- JRS role that the <key> external role is mapped to -->
<value>ROLE_USER</value>
</entry>
</map>
</property>
</bean>
<!--bean id="externalUserFolderProcessor" class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.ExternalUserFolderProcessor"
parent="abstractExternalProcessor"> <property name="repositoryService" ref="${bean.unsecureRepositoryService}"/>
</bean -->
<!-- ############ JRS Synchronizer ############ -->
答案 1 :(得分:15)
答案是否定的,你不能。为什么呢?
因为LDAP标准将LDAP-SEARCH描述为具有4个参数的函数类型:
您对过滤器感兴趣。您有一个摘要here(它由Microsoft提供,用于Active Directory,它来自标准)。过滤器以布尔方式由类型Attribute Operator Value
的表达式组成。
所以你提供的过滤器没有任何意义。
从理论的角度来看,ExtensibleMatch允许在DN路径上使用buildind过滤器,但Active Directory不支持它。
据我所知,你必须在AD中使用一个属性来区分两个OU中的用户。
它可以是任何现有的discriminator属性,或者,例如从organizationalPerson
类继承的名为OU的属性。你可以设置它(它不是自动的,如果移动用户就不会被维护),某些用户使用“staff”,而其他用户使用“vendor”,他们使用过滤器:
(&(objectCategory=person)(|(ou=staff)(ou=vendors)))
答案 2 :(得分:5)
很简单。只需更改端口。使用3268而不是389.如果您的域名 DOMAIN.LOCAL ,则在搜索中将 DC = DOMAIN,DC = LOCAL
端口3268:此端口用于专门针对全局编录的查询。发送到端口3268的LDAP请求可用于搜索整个林中的对象。但是,只能返回标记为要复制到全局编录的属性。
端口389:此端口用于从域控制器请求信息。发送到端口389的LDAP请求可用于仅在全局编录的主域中搜索对象。但是,应用程序可以获取所有搜索对象的属性。
答案 3 :(得分:2)
我不认为这可能与AD有关。 distinguishedName属性是我所知道的唯一包含您要搜索的OU片段的东西,因此您需要一个通配符来获取这些OU下的对象的结果。不幸的是,DN上的通配符isn't supported。
如果可能的话,我真的会在使用OU = Staff ...和OU = Vendors ...作为基本DN的2个查询中执行此操作。
答案 4 :(得分:1)
与LDAP专家交谈后,这种方式不可能。一个查询无法搜索多个DC或OU。
您的选择是:
- 运行多个查询并解析结果。
- 使用过滤器根据AD组或名称等不同属性查找所需的用户/对象。
醇>
答案 5 :(得分:1)
ou:dn:=<val>
语法对于 OP 的问题,这样做的方法是:
ldapsearch -b "DC=my,DC=super,DC=org" <other_options> "(|(ou:dc:=Staff)(ou:dc:=Vendors))"
原则上,您的情况很棘手,因为 OU 值不会出现在用户的 ldapsearch
输出中 -- OU 值是 DN 的一部分。
比如这里的搜索结果:
[root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" cn=testuser2
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: cn=testuser2
# requesting: ALL
#
# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org
cn: testuser2
displayName: pgtest
gidNumber: 500
givenName: testuser2
homeDirectory: /home/testuser2
loginShell: /bin/sh
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
userPassword:: e01ENX1GMnFxVVpDTjh4VVJveGg5bkJBcGF3PT0=
sn: testuser2
uidNumber: 1012
uid: testuser2
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
没有 ou:
行,因为 OU 属于 dn:
行。因此,如果您在搜索中添加 ou
,您会看到它是 requesting: ou
而不是 requesting: ALL
,但没有列出任何属性:
[root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" cn=testuser2 ou
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: cn=testuser2
# requesting: ou
#
# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
搜索 OU 会给你结果,但它们只是 OU 对象,而不是用户本身:
[root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" "(|(OU=IN)(OU=AU))"
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: (|(OU=IN)(OU=AU))
# requesting: ALL
#
# IN, example.org
dn: ou=IN,dc=example,dc=org
ou: IN
objectClass: organizationalUnit
objectClass: top
# AU, example.org
dn: ou=AU,dc=example,dc=org
ou: AU
objectClass: organizationalUnit
objectClass: top
# IN, IIQ, example.org
dn: ou=IN,ou=IIQ,dc=example,dc=org
objectClass: organizationalUnit
objectClass: top
ou: IN
# AU, IIQ, example.org
dn: ou=AU,ou=IIQ,dc=example,dc=org
ou: AU
objectClass: organizationalUnit
objectClass: top
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
但是,ldapsearch
允许您使用 ou:dn:=<val>
语法提取部分 DN:
[root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" "(&(displayname=pgtest)(|(ou:dn:=IN)(ou:dn:=AU)))" cn displayname
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: (&(displayname=pgtest)(|(ou:dn:=IN)(ou:dn:=AU)))
# requesting: cn displayname
#
# testuser3, AU, example.org
dn: cn=testuser3,ou=AU,dc=example,dc=org
cn: testuser3
displayName: pgtest
# testuser4, IN, example.org
dn: cn=testuser4,ou=IN,dc=example,dc=org
cn: testuser4
displayName: pgtest
# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org
cn: testuser2
displayName: pgtest
# testuser1, IN, IIQ, example.org
dn: cn=testuser1,ou=IN,ou=IIQ,dc=example,dc=org
cn: testuser1
displayName: pgtest
# testuser14, IN, example.org
dn: cn=testuser14,ou=IN,dc=example,dc=org
cn: testuser14
displayName: pgtest
# search result
search: 2
result: 0 Success
# numResponses: 6
# numEntries: 5