1

I have a catch 22.

I am implementing a service client whose responsibility is to authenticate a user at an LDAP server. The client accepts a userid and password, determines the userDn, and invoke a request to the LDAP server.

My problem is the way spring ldap template is setup at the moment. The LdapTemplate requires a ContextSource at bean creationtime. The ContextSource is configured at creation time to some value (ldapurl, userdn, password). But I realized that my ContextSource will change with each user. Each user opens a connection based on the user's DN. So, my contextsource is different per user and therefor creating a ContextSource at beancreation time(container startup) is not the right place. And, there is no way of overriding the ContextSource (with the userid/password) through the LdapTemplate AFAIK.

So, is it a good idea to create an Ldap ContextSource object explicitly in my code by initializing it explicitly with the actual userid and password (and the url of which is a constant over all users) and update my LdapTemplate bean by using the setter method of LdapTemplate? After my client call I will dispose the ContextSource by setting it to null (the template outlives the operation because it is a bean living in the spring container. So it could be reused and therefor the previous information on the context must not be available.)

Question: Is there another solution to this problem as described above?

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
user2120188
  • 427
  • 1
  • 4
  • 16
  • Is it a good idea to change a singleton bean which is used by multiple threads... What happens if you change the source from 10 threads simultaneously?... So is it a good idea, no it isn't. – M. Deinum Feb 08 '17 at 09:07
  • 1
    Instead set a `AuthenticationSource` on the `ContextSource`, the default uses a hardcoded instance. You can make it so that it will retrieve the user/password from a `ThreadLocal` or if you are using Spring Security (which I suggest instead of creating your own solution) you can use the `SpringSecurityAUthenticationSource`. – M. Deinum Feb 08 '17 at 09:12
  • @M.Deinum Having read your comment about the template being a singleton makes me realize that this approach could be a wrong choice. That is, the template declared in a spring configuration and being updated with a new contextsource instance by different threads. Indeed if these threads work concurrently they access the same template which has been updated by different threads each with their own version of contextsource! Not the way to go. Another way, the ldaptemplate could be defined/created also within the method which implements the connection to the ldapserver. – user2120188 Feb 08 '17 at 19:22
  • The ldaptemplate will no longer be be a spring bean but it will be created by my code. The same for contextsource. Besides your suggestion about the AuthenticationSource is there also another solution? (If not using springsecurity) – user2120188 Feb 08 '17 at 19:32
  • Instead of creating all those objects the `AuthenticationSource` is the easiest (apart from using Spring Security). – M. Deinum Feb 08 '17 at 19:35
  • Can you point me to an example using the authenticationSource? I ve just checked out this interface but I wonder what is the point of implementing this interface if I can not pass the userid and password from within my method. May be I am missing something...? – user2120188 Feb 08 '17 at 19:58
  • You store them in a `ThreadLocal` inside your method and you have an `AuthenticationSource` which retrieves them from the `ThreadLocal`. That way you have a thread safe implementation. Just make sure you clear the thread local after the request finished. – M. Deinum Feb 08 '17 at 20:00
  • Ok. I get it, your suggestion. Unfortunately this is not the direction I can proceed with. My authentication service client is depending on a username-password combination as method arguments. ThreadLocal fits indeed with the AuthenticationSource approach. Apparently it is the only "clean" and safe solution... :-(. I am afraid that I don't have other alternatives, other than your suggestion and my suggestion I described before. That is, creating myself the template and contextsource in the method which calls the ldapserver. In order to be threadsafe. – user2120188 Feb 08 '17 at 20:20
  • I still don't see the problem... Your authentication client doesn't need to change the signature, only your implementation needs to change... And in the method you just set the values. You don't really want to create an `LdapTemplate` each time you need one, you also need to create the other objects needed all in all quite the overkill for a simple call (and it is quite a heavy operation as well). – M. Deinum Feb 08 '17 at 20:26
  • I understand. I will check that out. In a nutshell, userid and password would be put on on a ThreadLocal at the beginning of the request (in the controller) and down the road the serviceclient will offload the userid and password from thread/threadlocal and invoke a call to the ldapserver. The AuthenticationSource is part of ldaptemplate so that userid and password are accessed in threadlocal. This approach would be safe (concurrently) and the same contextsource, that is the AuthenticationSource, would service connections with different userdn / passwords. (Right?) – user2120188 Feb 08 '17 at 21:00
  • Just checked the source code of LdapTemplate and discovered or concluded that there is not much happening with a LdapTemplate at creation/construction time. Actually nothing happening other than an assignment of ContextSource instance. The setters are just ordinary property setters. So no heavy lifting here either. The next call on LdapTemplate would be one of its methods like search(...) or authenticate(...) which does not change the internal state of LdapTemplate itself. So, even though LdapTemplate could be a shared object by different threads concurrently, it is still safe. – user2120188 Feb 08 '17 at 21:43
  • So, creating an instance of LdapTemplate in a method for each request won't demand much cost. Most probably ContextSource would cost more than LdapTemplate. So, I think relocating LdapTemplate from spring configuration to method level and creating a template on request basis is ok and safe.. – user2120188 Feb 08 '17 at 21:48

0 Answers0