LDAP根查询语法,用于搜索多个特定OU

时间:2012-02-07 22:27:26

标签: active-directory ldap ou

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

6 个答案:

答案 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="(&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 ############ -->

答案 1 :(得分:15)

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

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

  1. 应开始搜索的节点,即区分名称(DN)
  2. 您想要带回的属性
  3. 搜索的深度(基础,一级,子树)
  4. 过滤器
  5. 您对过滤器感兴趣。您有一个摘要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。

您的选择是:

  
      
  1. 运行多个查询并解析结果。
  2.   
  3. 使用过滤器根据AD组或名称等不同属性查找所需的用户/对象。
  4.   

答案 5 :(得分: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: 行。因此,如果您在搜索中添加 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