Implementing the AppFuse DAO layer with Spring LDAP
This week, I've been helping a click kickstart an application using AppFuse. The first order of business was re-writing the backend to support LDAP. They'd like to keep the Hibernate implementation in place, but they'd also prefer to have the option to use LDAP. Since a database will still be used to manage entities outside of User and Role, the LDAP implementation I have continues to maintain a userId and username in the database.
I'm pretty impressed that I was able to get 90% of the functionality completed in 2 days. Of course, it wouldn't have been possible w/o the excellent Spring LDAP project, nor the good ol' Acegi Security project. I'm deploying on Geronimo using the Apache Directory Plugin for LDAP. Getting a custom UserDetailsService working wasn't too difficult, but I am still having some issues with CRUDing LDAP:
- I get an Undefined Attribute Type error when modifying the non-String attributes in a User. This is quite strange since all the attributes are stored as Strings in LDAP.
- I get the same error when trying to remove a user from a role.
- There's no LdapUnit (like DbUnit) to delete/insert users and roles before running tests. I tried to use the LdapTestServer from Acegi, but no dice.
- Since the project has two versions (Hibernate or LDAP) in the source tree, the LDAP and Hibernate tests won't both pass. This is because the schema for LDAP only has 2 columns in the app_user table, while the Hibernate version of the table has all columns. The simplest solution seems to be removing the not-null constraints on most of the columns in this table.
If anyone has experience implementing User->Role CRUD in LDAP with Spring LDAP, I'd love to hear your thoughts on these issues.
Hey Matt,
It's been over a year since I did some LDAP/Java programming, but I think the error you're getting (Undefined Attribute Type) is related to those attributes not being part of "top", "person", or "inetOrgPerson". (Their being non-Strings is a coincidence.) Those problematic attributes are probably part of the "user" class, so I'd try changing the one line to:
and see what happens. If I recall correctly, the user class is MS AD specific. Note that different LDAP-compatible directory servers define users differently. Don't expect this code to be portable from AD to eDirectory to OpenLDAP. You may need a different implementation for each platform (unless Spring is doing some magic here. It wouldn't be the first time. :-).
Posted by kelzer on October 11, 2006 at 08:18 PM MDT #
Posted by Matt Raible on October 11, 2006 at 09:09 PM MDT #
Hey Matt,
What LDAP server are you using? I think I'm on the right track, but without more info I can't be much help, because every LDAP server treats users differently. Where are you getting the names of those attributes? (accountEnabled, etc.) I'm pretty sure they have to exist within one of those objects listed in the objectclass list. My guess is you're using OpenLDAP. I've worked with AD, Novell eDirectory, and Oracle Internet Directory (OID). They all do things differently when it comes to users.
Check out these LDAP error codes. Error 17 states: LDAP_UNDEFINED_ENGINE: Indicates that the attribute specified in the modify or add operation does not exist in the LDAP server's schema.
Active Directory actually uses a single attribute named "userAccountControl" that's used by the "user" class which stores flags for the locked state, password expiration state, etc. As I've said, other directory services do things differently. Novell eDirectory has a class named "ndsLoginProperties" that has attributes for those kinds of things. IBM Tivoli LDAP Server uses an attribute named "pwdLockout".
It's unfortunate that the LDAP standard doesn't standardize a lot of this type of thing.
Posted by kelzer on October 11, 2006 at 09:42 PM MDT #
AFAICT, the attributes are all named the same. The strange thing is the error only occurs when I modify certain attributes - most of the attributes can be modified just fine. You're probably right, I'm just not seeing it.
Posted by Matt Raible on October 11, 2006 at 09:49 PM MDT #
Posted by Mattias Arthursson on October 13, 2006 at 01:58 PM MDT #
And here's my Java code for removing a user from a role:
RoleDaoLdap.saveRole(Role role) is:
RoleDaoLdap.saveRole() works fine when I adding a new uniquemember attribute, it just fails when I try to remove one.
Posted by Matt Raible on October 13, 2006 at 02:07 PM MDT #
Posted by Ulrik Sandberg on October 13, 2006 at 04:06 PM MDT #
Posted by Matt Raible on October 13, 2006 at 04:14 PM MDT #
Posted by Mattias Arthursson on October 14, 2006 at 06:56 AM MDT #
Posted by anil on September 09, 2008 at 05:02 AM MDT #
Posted by anil on September 09, 2008 at 08:04 AM MDT #