Announcement Announcement Module
Collapse
No announcement yet.
[beginner] Can't get LDAP to work (LimitExceededException) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • [beginner] Can't get LDAP to work (LimitExceededException)

    Hello there!

    Since it's my first message, I'm gonna introduce myself a bit.

    I've been using AppFuse for a project, which comes with Spring framework.

    I've been asked to be able to list a LDAP directory and display a table resulting from this request. I know how to do that with a Database using Hibernate (included in AppFuse, too), but I didn't really know how to deal with LDAP directories, until I hear about spring-ldap.

    I read some docs about it, and it seems to be exactly what I am looking for... but I can't get it work!

    So I have a JSP that should display a table containing the information I want from the LDAP directory. This JSP is connected by a class Action which calls the getUtilisateurs() method, which is the same as findAll() in the spring-ldap tutorials I've seen so far.

    This method is implemented in a class called UtilisateurDaoLdap.java like this:

    Code:
    	public List getUtilisateurs() {
    		EqualsFilter filter = new EqualsFilter("objectclass", "person");
    		return ldapTemplate.search(DistinguishedName.EMPTY_PATH, filter
    				.encode(), getContextMapper());
    	}
    When this method is called, an exception is thrown:

    Code:
    org.springframework.ldap.LimitExceededException: [LDAP: error code 3 - Timelimit Exceeded]; nested exception is javax.naming.TimeLimitExceededException: [LDAP: error code 3 - Timelimit Exceeded]; remaining name '/'
    Caused by: javax.naming.TimeLimitExceededException: [LDAP: error code 3 - Timelimit Exceeded]; remaining name '/'
    But normally, all the information needed to connect to the LDAP directory is set in a ApplicationContext-*.xml

    Code:
       	<bean id="contextSource"
    		class="org.springframework.ldap.core.support.LdapContextSource">
    		<property name="url" value="ldaps://path.to.dir:636" />
    		<property name="base" value="c=fr" />
    		<property name="userDn" value="cn=xxx,ou=xxx,o=xxx,c=fr" />
    		<property name="password" value="xxx" />
    	</bean>
    	<bean id="ldapTemplate"
    		class="org.springframework.ldap.core.LdapTemplate">
    		<constructor-arg ref="contextSource" />
    	</bean>
    	<bean id="utilisateurDao"
    		class="com.steria.mireor.admin.dao.ldap.UtilisateurDaoLdap">
    		<property name="ldapTemplate" ref="ldapTemplate" />
    	</bean>
    Would anybody have an idea?

    I am brand new to both LDAP and spring-ldap, so it might be something really simple I didn't get... or not

    Thanks in advance!

  • #2
    If your database contains lots of persons, you might exceed a time limit using your rather generous filter "objectclass=person". I suggest you use a specific person in your filter. For example, "cn=John Doe". If you still get TimeLimitExceededException, then the problem most likely lies elsewhere.

    Comment


    • #3
      Originally posted by ulsa View Post
      If your database contains lots of persons, you might exceed a time limit using your rather generous filter "objectclass=person". I suggest you use a specific person in your filter. For example, "cn=John Doe". If you still get TimeLimitExceededException, then the problem most likely lies elsewhere.
      Thanks! It was indeed the case; the directory is really huge and requesting for everything was just too much

      I just did a test with a very restrictive filter, as you suggested, and got all the information I needed.

      Thank you!

      Comment


      • #4
        Hm...

        Now there is something I don't really understand.

        Applying a filter such as "cn=Joh DOE" will give me all information I requested (like its sn, mail, etc.) for this specific user.

        But when I try to use a less specific filter, such as ou=SVO (a region abbreviation mentioned in my LDAP directory), I got one result, but not a list of results... looks as if the result returned was "yes, there is an object called ou=SVO", whereas I am looking for a result like "there is a object called ou=SVO, and all its subobjects (CN) are...". In other words, I would like to get a list of CN... How can I achieve that?

        And, by the way, what does the SearchControls.SUBTREE_SCOPE attribute stands for? I didn't get the meaning of SearchControls...

        Thanks in advance for your help...

        P.S.: my getter method now looks like

        Code:
        	public List getUtilisateurs() {
        		return ldapTemplate.search(DistinguishedName.EMPTY_PATH,"(ou=SVO)" ,SearchControls.SUBTREE_SCOPE, getContextMapper());
        	}
        Last edited by Pierrre; Jul 15th, 2008, 05:29 AM.

        Comment


        • #5
          The scope of a search can be either "here" (OBJECT_SCOPE), "one level below only" (ONELEVEL_SCOPE), or "recursively" (SUBTREE_SCOPE). By far the most common is to search recursively, so there are methods in LdapTemplate where you don't have to give the scope; they search recursively by default. They take only search base, filter and mapper. I recommend that you use those, unless you want to perform more advanced searches (for example search for root contexts as described in this thread).

          The search method that you show will begin at the given search base and then search for the given filter according to the scope given. You specified subtree scope, which means you can replace it with this code:

          Code:
          public List getUtilisateurs() {
             return ldapTemplate.search("", "(ou=SVO)", getContextMapper());
          }
          An LDAP database is really a tree where the nodes (entries) have attributes. Each node has a unique address in the tree. This address is called the Distinguished Name (DN). It can look like this: "cn=John Doe, ou=SVO". If you search from the root of the tree ("") with the filter "(ou=SVO)", you will get the entries that have attributes that match that filter. In your case, you probably have one node in the tree called "ou=SVO", so you'll get that. If you want certain entries below that node, you set the search base to that node and search recursively with a suitable filter, like this:

          Code:
          ldapTemplate.search("ou=SVO", "(cn=*)", getContextMapper());

          Comment


          • #6
            Thank you very much for these explanations! It's much more clear to me now!

            I'm using LDAP Browser to browse my LDAP dir, and it looks like this:

            Code:
            c=fr
            +--O=...
            +--O=...
            +--O=EDFGDF
                +--OU=...
                +--OU=DEPT
                    +--OU=SVO
                        +--OU=...
                        +--CN=...
                        +--OU=OSGE
                            +--CN=Somebody
                            +--CN=Somebody Else
                            +--CN=...
                        +--OU=...
            +--O=...
            +--O=...
            At first, I tried to call the search method like this:

            Code:
            return ldapTemplate.search("ou=OSGE", "(cn=*)", getContextMapper());
            No errors, but no results returned

            Then I tried with the full path to the nodes I'm looking for:

            Code:
            return ldapTemplate.search("ou=OSGE,ou=SVO,ou=DEPT,o=EDFGDF,c=fr", "(cn=*)", getContextMapper());
            Same... nothing returned.

            Once again, I manage to get all the info I want when I use the CN parameter directly. For instance, if I use this:

            Code:
            return ldapTemplate.search("", "cn=Somebody Else", getContextMapper());
            I will get all the info (e-mail, family name, etc.) from the user whom CN is "Somebody Else".

            I don't really have any clue on how to reach those users (CN)... Weird! Any idea?
            Last edited by Pierrre; Jul 15th, 2008, 10:08 AM.

            Comment


            • #7
              Could you post your configuration as well? I suspect the problem is related to the "base" property.

              Comment


              • #8
                What do you mean by "configuration"? My xml files or something?

                Comment


                • #9
                  oh, I think I know what you mean; here is what I put in my xml config file:

                  Code:
                     <bean id="contextSource"
                  		class="org.springframework.ldap.core.support.LdapContextSource">
                  		<property name="url" value="ldaps://thisis.myserver.fr:636" />
                  		<property name="base" value="c=fr" />
                  		<property name="userDn" value="cn=projectname,ou=appli,o=edf,c=fr" />
                  		<property name="password" value="secret" />
                  	</bean>
                  	<bean id="ldapTemplate"
                  		class="org.springframework.ldap.core.LdapTemplate">
                  		<constructor-arg ref="contextSource" />
                  	</bean>
                  	<bean id="utilisateurDao"
                  		class="com.steria.mireor.admin.dao.ldap.UtilisateurDaoLdap">
                  		<property name="ldapTemplate" ref="ldapTemplate" />
                  	</bean>
                  Values in italic have been modified, but everything else is exactly as is. Hope this helps?

                  Comment


                  • #10
                    OK, you have "c=fr" as your base. This means that all LdapTemplate operations automatically prepends "c=fr" to all DNs. Looking at your first attempt:

                    Code:
                    return ldapTemplate.search("ou=OSGE", "(cn=*)", getContextMapper());
                    Here you use "ou=OSGE" as your search base (the node in the tree where the search should begin). Your base, "c=fr", will be prepended, giving this DN: "ou=OSGE, c=fr". According to your tree graph, there is no such node and you'll get no results.

                    In your next attempt, you're very close:

                    Code:
                    return ldapTemplate.search("ou=OSGE,ou=SVO,ou=DEPT,o=EDFGDF,c=fr", "(cn=*)", getContextMapper());
                    Here the problem is that you already have the base, "c=fr", first in your search base DN. The base will be prepended regardless, giving you this DN: "ou=OSGE,ou=SVO,ou=DEPT,o=EDFGDF,c=fr,c=fr". Same problem as before; no such node.

                    Your third attempt succeeds simply because your search base is at the root of the tree. You will find all entries with that cn in the whole tree.

                    Code:
                    return ldapTemplate.search("", "cn=Somebody Else", getContextMapper());
                    You should try this code:

                    Code:
                    return ldapTemplate.search("ou=OSGE,ou=SVO,ou=DEPT,o=EDFGDF", "(cn=*)", getContextMapper());

                    Comment


                    • #11
                      It now works perfectly!

                      Thank you so much for the time you took to explain me all those details and for the explanations you provided!

                      Comment


                      • #12
                        We tend to refer to DNs that expect a base to be prepended as "relative DNs", in contrast to "absolute DNs" which always are the full path.

                        One thing to remember is that the base is prepended to DNs in all LdapTemplate operations (lookup, search, bind, modifyAttributes, etc), but never to the authentication DN. The authentication DN should always be an absolute DN. You used as userDn "cn=projectname,ou=appli,o=edf,c=fr", which is correct even though your base is "c=fr".

                        Another thing to remember is that group members are absolute DNs. For example, if you have an entry of objectclass groupOfUniqueNames, the values of the uniqueMember attribute are absolute DNs.

                        Comment

                        Working...
                        X