If I want to use users from an LDAP source, how to do that?
Also, when deploying in production, I would like to use my container's
LDAP integration capabilities. Is this possible?
Thanks a lot!
A nicer to code solution would be to use "Spring LDAP", a subproject
of the Spring Framework, which eliminates most of the ugly, repetitive
JNDI code and gives you nice callbacks. Think of it like Spring JDBC
is on top of regular JDBC.
A sample snippet with Spring LDAP is the following:
public class LDAPContactDAO implements ContactDAO{
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
public List getAllContactNames() {
return ldapTemplate.search("", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
}
(taken from here: http://www.javaworld.com/javaworld/jw-06-2007/jw-06-springldap.html
)
which is the shorter version to what you would need to write with JNDI
like the following:
public class SimpleLDAPClient {
public static void main(String[] args) {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389/
ou=system");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
DirContext ctx = null;
NamingEnumeration results = null;
try {
ctx = new InitialDirContext(env);
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)",
controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult)
results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
System.out.println(" Person Common Name = " + cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
}
}
}
}
}
Here is a sample by the creators of Spring LDAP on how to do
authentication using Spring LDAP:
http://blog.jayway.com/2009/02/02/simple-authentication-using-spring-ldap/
So, this is what I tried:
1) Started with the yabe sample, verified that everything is working.
Also, installed Apache Directory and Studio.
2) Added the spring module support and my application-context.xml.
3) Copied spring ldap jars into the spring module lib directory.
4) Wrote a Person model class and a utility class (copied from the
Spring LDAP sample (http://static.springsource.org/spring-ldap/site/
reference/html/dirobjectfactory.html#d0e1013) with a couple of
modifications)
5) Then, I tried to change the authenticate method in the Security
class and the setConnectedUser method in Admin.
Here, I get a bit confused and also ran into a couple of problems:
User user = User.find("byEmail", Security.connected()).first();
How do I change this so that I can use spring ldap instead? The
"byEmail" operates on JPA whereas I need to find on LDAP. I notice
that it's not taking any parameter so how can I make my LDAP search?
2nd, I also get this error:
The file /app/controllers/Security.java could not be compiled. Error
raised is : Secure.Security cannot be resolved to a type.
In the console, I can see this:
play.exceptions.JavaCompilationException: Secure.Security cannot be
resolved to a type
at play.classloading.ApplicationCompiler
$2.acceptResult(ApplicationCompiler.java:240)
at
org.eclipse.jdt.internal.compiler.Compiler.handleInternalException(Compiler.java:
551)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:
409)
at
play.classloading.ApplicationCompiler.compile(ApplicationCompiler.java:
271)
at
play.classloading.ApplicationClassloader.getAllClasses(ApplicationClassloader.java:
373)
at
play.classloading.ApplicationClassloader.getAssignableClasses(ApplicationClassloader.java:
400)
at {module:crud}/app/views/tags/crud/types.tag.(line:3)
at play.templates.Template.render(Template.java:238)
at play.templates.Template$ExecutableTemplate.invokeTag(Template.java:
394)
at {module:crud}/conf/routes.(line:4)
at play.templates.Template.render(Template.java:238)
at play.mvc.Router.parse(Router.java:88)
at play.mvc.Router.parse(Router.java:110)
at play.mvc.Router.load(Router.java:36)
at play.mvc.Router.detectChanges(Router.java:131)
at play.Play.detectChanges(Play.java:466)
at play.Invoker$Invocation.init(Invoker.java:98)
at Invocation.HTTP Request(Play!)
So, I then tried reverting the changes in Security and Admin classes
but the last error still happens.
Please advise.
Cheers.
But in general, I think that the following is incorrect:
" User.find("byEmail", Security.connected()).first(); "
You need to replace that with your actual Ldap-Searcher-Class, because
this line will hit the database and not your LDAP server. You can
create an instance of that class in your Security controller yourself
or use dependency injection for that, so you would end up with
something similar to the following:
String username = ...
String password = ...
MyLdapSearcher ldap = new MyLdapSearcher();
User u = ldap.search(username, password);
Thanks for your advice. It was really helpful.
I'm now able to authenticate against LDAP (tested against Apache DS).
I used the Spring Module and Spring LDAP.
There are still a few limitations left which I'll try to clear and
then I hope I can contribute a write up.
Cheers.
--
You received this message because you are subscribed to a topic in the Google Groups "play-framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/play-framework/-xZ9Ei037DI/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.