I am using spring security to authenticate users logging into a webapp. Authentication is currently done with ldap.
Between my webapp and my ldap server lies a firewall. After 50 minutes of inactivity, the firewall flushes idle ldap connections.
Spring security sometimes reuses existing connections, but not always. If it picks a connection closed by my firewall, the login will fail.
The exception I find in my Tomcat log is the following.
org.springframework.ldap.ServiceUnavailableException: ldap:389; socket closed; nested exception is javax.naming.ServiceUnavailableException
More specifically, connections causing issues are the ones used for search requests. They're not systematically closed by the framework. Bind requests are always made on a new connection that's closed at the end of the request.
In my app a search request is issued after a bind because of a custom LdapAuthoritiesPopulator granting access only to users with particular roles. I have verified the default LdapAuthoritiesPopulator issues search requests in the same manner.
Is it normal for search request connections to stay open almost indefinitely? If it is, is there a way I can change the way spring security manages its connections?
I'm also interested to know if there is a better way than using a custom LdapAuthoritiesPopulator to enforce a role constraint during authentication.
My problem persists after trying easy upgrades:
- spring-security 3.1.7 (up from 3.1.2)
- spring-ldap-core 2.0.2 (up from 1.3.0)
- spring-ldap 1.3.1 (up from 1.3.0)
Thanks.
The solution is to use ldap-spring pooling and validation. http://docs.spring.io/spring-ldap/docs/1.3.x/reference/html/pooling.html
A first good step is to define
<beans:property name="pooled" value="false"/>
. With that, all requests - bind or search - are made on an independent connection.If you have a lot of ldap connections to handle and wish to minimize connection overhead, then you have to setup additional objects to define your connection pool behavior. It is all well explained in the doc.
As of spring-ldap 1.3, you need to add commons-pool 1.6 to your project.