35

我需要运行一个 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 查询中此类表达式的正确语法。

4

6 回答 6

29

你可以!!!简而言之,将其用作连接字符串:

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 专家:)该死的,我已经到处寻找这个解决方案将近 2 天了,几乎放弃了,习惯了我可能不得不手动实现这个显然非常常见的场景的想法(使用 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="(&amp;(member={0})(&amp;(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>(&amp;(sAMAccountName={0})(&amp;((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 ############ -->

于 2013-09-27T06:33:21.923 回答
16

答案是否定的,你不能。为什么?

因为 LDAP 标准将 LDAP-SEARCH 描述为具有 4 个参数的函数:

  1. 应开始搜索的节点,即专有名称 (DN)
  2. 你想带回来的属性
  3. 搜索深度(基础、一级、子树)
  4. 过滤器

您对过滤器感兴趣。您在这里有一个摘要(它是由 Microsoft 为 Active Directory 提供的,它来自一个标准)。过滤器以布尔方式由 type 的表达式组成Attribute Operator Value

所以你给的过滤器没有任何意义。

从理论上讲,ExtensibleMatch允许在 DN 路径上构建过滤器,但 Active Directory 不支持它。

据我所知,您必须在 AD 中使用一个属性来区分两个 OU 中的用户。

它可以是任何现有的鉴别器属性,或者,例如从organizationalPerson类继承的称为 OU 的属性。您可以为某些用户设置它(它不是自动的,并且如果您移动用户将不会被维护)为某些用户设置“员工”,为其他用户设置“供应商”,他们使用过滤器:

(&(objectCategory=person)(|(ou=staff)(ou=vendors)))
于 2012-02-08T04:32:01.903 回答
6

这很简单。换个端口就好了。使用 3268 而不是 389。如果您的域名DOMAIN.LOCAL,请在搜索中输入DC=DOMAIN,DC=LOCAL

端口 3268:此端口用于专门针对全局编录的查询。发送到端口 3268 的 LDAP 请求可用于搜索整个林中的对象。但是,只能返回标记为复制到全局编录的属性。

端口 389:此端口用于向域控制器请求信息。发送到端口 389 的 LDAP 请求只能用于搜索全局编录主域内的对象。但是,应用程序可以获取搜索对象的所有属性。

于 2016-01-27T13:21:13.777 回答
2

我认为这对于 AD 来说是不可能的。distinctName 属性是我所知道的唯一包含您尝试搜索的 OU 片段的属性,因此您需要一个通配符来获取这些 OU 下对象的结果。不幸的是, DN不支持通配符。

如果可能的话,我真的会考虑在使用 OU=Staff... 和 OU=Vendors... 作为基本 DN 的 2 个查询中执行此操作。

于 2012-02-07T23:50:30.800 回答
1

在与 LDAP 专家交谈后,这种方式是不可能的。一个查询不能搜索多个 DC 或 OU。

您的选择是:

  1. 运行超过 1 个查询并解析结果。
  2. 使用过滤器根据 AD 组或名称等不同属性查找所需的用户/对象。
于 2017-08-08T21:07:06.170 回答
1

tl;dr -- 使用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:行。因此,如果您在搜索中添加 an 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提取部分 DN :ou:dn:=<val>

[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
于 2021-05-04T06:54:47.393 回答