I. Introduction▲
Il est n'est pas nécessaire d'utiliser ou de connaitre Spring pour utiliser ce tutoriel. Il n'est pas non plus nécessaire d'installer un serveur Ldap, car nous utiliserons le serveur public de www.openldap.com.
Vous trouverez les sources complètes de ce tutoriel à la fin du document.
II. Remerciements▲
Merci à Baptiste Wicht pour sa relecture attentive.
III. Installation d'un browser LDAP▲
Afin de pouvoir consulter le contenu du serveur LDAP, nous avons besoin d'un browser LDAP.
Je vous propose d'utiliser Softera LDAP Browser.
- Télécharger et installer Softera LDAP Browser 2.6 sur le site de Softerra : http://www.ldapadministrator.com/download.htm. et en faire une installation complète.
- Utiliser le browser pour aller sur le serveur préenregistré de openLDAP : www.openldap.com sur le port 389.
- Ouvrir successivement les nœuds : OpenLDAP / cn = DirectoryManager / ou=People .Sélectionner le Nœud avec le uid = Kurt.
Un clic droit dans les propriétés de Kurt permet de voir l'adresse complète de Kurt sur le serveur :
ldap://www.openldap.com:389/uid=kurt,ou=People,dc=OpenLDAP,dc=Org
Cette adresse se compose de deux parties :
partie 1 : www.openldap.com:389 est l'adresse Internet et le port du serveur LDAP ;
partie 2 : uid=kurt,ou=People,dc=OpenLDAP,dc=Org est le Distinguish Name de l'enregistrement kurt. Il représente le chemin d'accès dans l'arbre LDAP à kurt.
Maintenant que nous avons vu comment obtenir les informations sur Kurt via un Browser LDAP, nous allons faire la même chose avec du Java !
IV. Téléchargement de Spring LDAP▲
Télécharger la bibliothèque spring-ldap-bin-with-dependencies-1.2.1.zip sur le site http://www.springframework.org/ldap
Décompresser cette archive.
Dans le répertoire dist se trouve spring-ldap-1.2.1.jar qui doit être placé dans le CLASSPATH du projet pour pourvoir faire fonctionner ce tutoriel.
Dans le répertoire lib se trouve commons-lang.jar,commons-loggin.jar,springbeans. jar,spring-core.jar, toutes ces bibliothèques doivent aussi être ajoutées au CLASSPATH.
V. Création d'une connexion avec le serveur LDAP.▲
Spring LDAP utilise la notion de ContextSource pour définir une connexion au serveur LDAP.
Créons une factory pour récupérer un ContextSource correct. ContextSource étant une interface, nous utiliserons LdapContextSource qui est une implémentation fournie par Spring LDAP
public
class
LdapContextSourceFactory {
public
static
ContextSource getLdapContextSource
(
) throws
Exception {
LdapContextSource ldapContextSource =
new
LdapContextSource
(
);
ldapContextSource.setUrl
(
"ldap://www.openldap.com:389"
);
ldapContextSource.setBase
(
"dc=OpenLDAP,dc=org"
);
ldapContextSource.afterPropertiesSet
(
);
return
ldapContextSource;
}
}
VI. Création de l'Objet Person▲
Spring LDAP permet de lire des enregistrements de personnes sous forme d'objet Person.
Voici notre class Person qui nous permettra d'obtenir une instance de Kurt. Uid est l'identifiant unique défini sur le serveur LDAP pour les Person.
package
com.neoneto.demo.springLdap1_2;
public
class
Person {
private
String uid;
private
String firstName;
private
String lastName;
public
String getFirstName
(
) {
return
firstName;
}
public
void
setFirstName
(
String firstName) {
this
.firstName =
firstName;
}
public
String getLastName
(
) {
return
lastName;
}
public
void
setLastName
(
String lastName) {
this
.lastName =
lastName;
}
public
String getUid
(
) {
return
uid;
}
public
void
setUid
(
String uid) {
this
.uid =
uid;
}
}
VII. Récupération d'un objet Person via un DAO▲
Il est possible d'utiliser le pattern DAO pour accéder aux objets Person. Voici comment procéder en quatre étapes.
- 1 Créer un Mapper de LDAP vers Java
Un AttributMapper permet d'instancier correctement notre classe Person. C'est lui qui effectue le mappage entre la Structure LDAP Person et le model Objet Java Person.
Par exemple l'attribut LDAP « givenName » sera placé dans l'attribut Person.firstName de l'objet Java p.setFirstName(attrs.get("givenName").get().toString());
Ce mapper est déclaré comme interne du DAO, car il ne doit pas être utilisé ailleurs que dans cette Dao.
public
class
PersonDao {
private
static
class
PersonAttributMapper implements
AttributesMapper
{
public
Person mapFromAttributes
(
Attributes attrs)
throws
javax.naming.NamingException {
Person p =
new
Person
(
);
p.setFirstName
(
attrs.get
(
"givenName"
).get
(
).toString
(
));
p.setLastName
(
attrs.get
(
"sn"
).get
(
).toString
(
));
p.setUid
(
attrs.get
(
"uid"
).get
(
).toString
(
));
p.setEmail
(
attrs.get
(
"mail"
).get
(
).toString
(
));
return
p;
}
}
}
- 2 Utiliser un LdapTemplate
L'exécution de requêtes LDAP se fait via un LdapTemplate.
public
class
PersonDao {
...
private
LdapTemplate ldapTemplate;
public
void
setLdapTemplate
(
LdapTemplate ldapTemplate) {
this
.ldapTemplate =
ldapTemplate;
}
...
}
- 3 Définir le Distinguish Name
Le Distinguish Name est le chemin d'accès à l'enregistrement de Person sur le serveur. La fonction BuildDn permet d'obtenir un Distinguish Name correct.
public
class
PersonDao {
...
private
Name buildDn
(
String uid) {
DistinguishedName dn =
new
DistinguishedName
(
);
dn.add
(
"ou"
, "People"
);
dn.add
(
"uid"
, uid);
return
dn;
}
...
}
- 4 Obtenir l'instance de la class Person
Il suffit d'utiliser la méthode lookup du ldapTemplate pour obtenir l'instance correspondant à la clef primaire, c'est-à-dire l'uid dans le cas des Objet Person.
public
class
PersonDao {
...
public
Person findByPrimaryKey
(
String uid) {
Name dn =
buildDn
(
uid);
return
(
Person) ldapTemplate.lookup
(
dn, new
PersonAttributMapper
(
));
}
...
}
VIII. Test de la DAO▲
- Créons une classe exécutable pour tester notre DAO.
public
class
TestLdap {
/** Retrieve a Kurt Person from LDAP server and display Kurt in
Standard Out */
public
static
void
main
(
String[] args) {
}
}
Cette classe exécutable ne prend en compte aucun argument.
- Ajoutons dans la méthode main le Context Source
// 1 Retrieve a LdapContextSource
ContextSource ldapContextSource =
null
;
try
{
ldapContextSource =
LdapContextSourceFactory.getLdapContextSource
(
);
}
catch
(
Exception e) {
System.out.println
(
"Impossible to get a LdapContextSource."
);
e.printStackTrace
(
);
}
- Il faut aussi obtenir un LdapTemplate.
// 2 Instanciate a LdapTemplate
LdapTemplate ldapTemplate =
new
LdapTemplate
(
);
ldapTemplate.setContextSource
(
ldapContextSource);
- Instancions un Dao et fournissons-lui le ldapTemplate.
// 3 instanciate a PersonDao
PersonDao dao =
new
PersonDao
(
);
dao.setLdapTemplate
(
ldapTemplate);
- La récupération de Kurt se fait simplement en utilisant la DAO.
// 4 retrieve a Person and display it
Person person =
dao.findByPrimaryKey
(
"kurt"
);
System.out.println
(
"Uid: "
+
person.getUid
(
));
System.out.println
(
"FirstName: "
+
person.getFirstName
(
));
System.out.println
(
"LastName: "
+
person.getLastName
(
));
System.out.println
(
"Email: "
+
person.getEmail
(
) +
"
\n
"
);
Lorsque nous exécutons cette classe, nous obtenons dans la sortie standard :
Uid: kurt
LastName: Kurt
LastName: Zeilenga
Email: kurt@OpenLDAP.org
Ce qui correspond bien aux enregistrements contenus dans le serveur LDAP.
IX. Amélioration de la DAO▲
Ajoutons une méthode dans la DAO qui permet de récupérer une liste de personnes à partir de leur nom de famille.
La classe LikeFilter permet d'utiliser des filtres de recherches avec des WildCard :
public
List getPersonNamesByLastName
(
String lastName) {
AndFilter filter =
new
AndFilter
(
);
filter.and
(
new
EqualsFilter
(
"objectclass"
, "person"
));
filter.and
(
new
LikeFilter
(
"sn"
, lastName));
return
ldapTemplate.search
(
""
, filter.encode
(
),
new
PersonAttributMapper
(
));
}
Par exemple getPersonNamesByLastName(“E*”); retournera la liste des personnes dont le nom de famille commence par E.
Complétons la classe main avec un exemple d'utilisation de cette nouvelle fonctionnalité.
// 5 retrieve a list of person
List listPerson =
dao.getPersonNamesByLastName
(
"*e*"
);
for
(
Object object : listPerson) {
System.out.println
(
"Person: "
+
object);
}
L'exécution de la classe main retourne deux personnes dans la sortie standard.
X. Conclusion▲
Spring LDAP est une bibliothèque J2EE qui permet de récupérer simplement des enregistrements LDAP sous forme d'objets Java et d'affranchir le développeur Java de la connaissance des mécanismes de LDAP.
Spring LDAP permet aussi d'écrire sur le serveur LDAP. Reportez-vous à la documentation de référence de Spring LDAP qui explique très bien comment faire cela.
XI. Liens et références▲
La doc de Spring LDAP :http://static.springframework.org/spring-ldap/docs/1.1.2/reference/
L'api de Spring LDAP : http://static.springframework.org/spring-ldap/docs/1.1.2/api/
En savoir plus sur LDAP : http://www-sop.inria.fr/semir/personnel/Laurent.Mirtain/ldaplivre.html
Liste de serveurs LDAP public : http://www.emailman.com/ldap/public.html
Blog de l'auteur : http://getj2ee.over-blog.com/
XII. Contraintes techniques▲
Doc Version 1.0.4 - Publié le 19 janvier 2008 par David Gimelle, Revue le 3 avril 2008.
Ce tutoriel a été testé avec Windows Vista, Eclipse 3.2 et le jdk 1.5.0_06 le 17 janvier 2008.
XIII. Les sources de ce tutoriel▲
1- Person.java :
package
com.neoneto.demo.springLdap1_2;
public
class
Person {
private
String uid;
private
String firstName;
private
String lastName;
private
String email;
public
String getEmail
(
) {
return
email;
}
public
void
setEmail
(
String email) {
this
.email =
email;
}
public
String getFirstName
(
) {
return
firstName;
}
public
void
setFirstName
(
String firstName) {
this
.firstName =
firstName;
}
public
String getLastName
(
) {
return
lastName;
}
public
void
setLastName
(
String lastName) {
this
.lastName =
lastName;
}
public
String getUid
(
) {
return
uid;
}
public
void
setUid
(
String uid) {
this
.uid =
uid;
}
public
String toString
(
){
return
uid+
" - "
+
firstName+
" "
+
lastName;
}
}
2- PersonDao.java :
package
com.neoneto.demo.springLdap1_2;
import
java.util.List;
import
javax.naming.Name;
import
javax.naming.directory.Attributes;
import
org.springframework.ldap.core.AttributesMapper;
import
org.springframework.ldap.core.DistinguishedName;
import
org.springframework.ldap.core.LdapTemplate;
import
org.springframework.ldap.filter.AndFilter;
import
org.springframework.ldap.filter.EqualsFilter;
import
org.springframework.ldap.filter.LikeFilter;
public
class
PersonDao {
private
LdapTemplate ldapTemplate;
private
static
class
PersonAttributMapper implements
AttributesMapper
{
public
Person mapFromAttributes
(
Attributes attrs)
throws
javax.naming.NamingException {
Person p =
new
Person
(
);
p.setFirstName
(
attrs.get
(
"givenName"
).get
(
).toString
(
));
p.setLastName
(
attrs.get
(
"sn"
).get
(
).toString
(
));
p.setUid
(
attrs.get
(
"uid"
).get
(
).toString
(
));
p.setEmail
(
attrs.get
(
"mail"
).get
(
).toString
(
));
return
p;
}
}
public
Person findByPrimaryKey
(
String uid) {
Name dn =
buildDn
(
uid);
return
(
Person) ldapTemplate.lookup
(
dn, new
PersonAttributMapper
(
));
}
private
Name buildDn
(
String uid) {
DistinguishedName dn =
new
DistinguishedName
(
);
dn.add
(
"ou"
, "People"
);
dn.add
(
"uid"
, uid);
return
dn;
}
public
void
setLdapTemplate
(
LdapTemplate ldapTemplate) {
this
.ldapTemplate =
ldapTemplate;
}
public
List getPersonNamesByLastName
(
String lastName) {
AndFilter filter =
new
AndFilter
(
);
filter.and
(
new
EqualsFilter
(
"objectclass"
, "person"
));
filter.and
(
new
LikeFilter
(
"sn"
, lastName));
return
ldapTemplate.search
(
""
, filter.encode
(
),
new
PersonAttributMapper
(
));
}
}
3 - LdapContextSourceFactory.java :
package
com.neoneto.demo.springLdap1_2;
import
org.springframework.ldap.core.ContextSource;
import
org.springframework.ldap.core.support.LdapContextSource;
public
class
LdapContextSourceFactory {
public
static
ContextSource getLdapContextSource
(
) throws
Exception {
LdapContextSource ldapContextSource =
new
LdapContextSource
(
);
ldapContextSource.setUrl
(
"ldap://www.openldap.com:389"
);
ldapContextSource.setBase
(
"dc=OpenLDAP,dc=org"
);
ldapContextSource.afterPropertiesSet
(
);
return
ldapContextSource;
}
}
4 - TestLdap.java :
package
com.neoneto.demo.springLdap1_2;
import
java.util.List;
import
org.springframework.ldap.core.ContextSource;
import
org.springframework.ldap.core.LdapTemplate;
public
class
TestLdap {
/** Retrieve a Kurt Person from ldap server and display Kurt in
Standard Out */
public
static
void
main
(
String[] args) {
// 1 Retrieve a LdapContextSource
ContextSource ldapContextSource =
null
;
try
{
ldapContextSource =
LdapContextSourceFactory.getLdapContextSource
(
);
}
catch
(
Exception e) {
System.out.println
(
"Impossible to get a
LdapContextSource.");
e.printStackTrace
(
);
}
// 2 Instanciate a LdapTemplate
LdapTemplate ldapTemplate =
new
LdapTemplate
(
);
ldapTemplate.setContextSource
(
ldapContextSource);
// 3 instanciate a PersonDao
PersonDao dao =
new
PersonDao
(
);
dao.setLdapTemplate
(
ldapTemplate);
// 4 retrieve a Person and display it
Person person =
dao.findByPrimaryKey
(
"kurt"
);
System.out.println
(
"Uid: "
+
person.getUid
(
));
System.out.println
(
"FirstName: "
+
person.getFirstName
(
));
System.out.println
(
"LastName: "
+
person.getLastName
(
));
System.out.println
(
"Email: "
+
person.getEmail
(
) +
"
\n
"
);
// 5 retrieve a list of person
List listPerson =
dao.getPersonNamesByLastName
(
"*e*"
);
for
(
Object object : listPerson) {
System.out.println
(
"Person: "
+
object);
}
}
}