Pojednostavite pristup direktoriju s Spring LDAP-om

Spring LDAP je okvir zasnovan na Springu koji pojednostavljuje LDAP programiranje na Java platformi. U ovom detaljnom vodiču za korištenje Spring LDAP-a naučit ćete kako se okvir nosi s kodiranjem na niskoj razini koje zahtijeva većina LDAP klijenata, tako da se možete usredotočiti na razvoj poslovne logike vaše aplikacije. Također ćete vježbati jednostavne CRUD operacije pomoću Spring LDAP-a i naučiti o naprednijim operacijama, poput stvaranja dinamičkih filtara i pretvaranja LDAP unosa u Java grah.

Lagani protokol za pristup direktoriju bitna je komponenta većine današnjih implementacija velikih poduzeća. LDAP se prvenstveno koristi za pohranu podataka povezanih s korisničkim identitetom, poput korisničkog imena, lozinke i adrese e-pošte. Također se koristi u sigurnosnim implementacijama gdje je potrebno pohraniti korisnička prava pristupa u svrhu provjere autentičnosti i autorizacije.

Java imenovanje i sučelje direktorija (JDNI) API je koji se koristi za LDAP programiranje na Java platformi. Definira standardno sučelje koje se može koristiti u vašoj aplikaciji za interakciju s bilo kojim LDAP poslužiteljem. Nažalost, korištenje JNDI obično podrazumijeva pisanje puno niskorazinskog, ponavljajućeg koda. JNDI previše radi na jednostavnim postupcima, poput osiguranja da su resursi pravilno otvoreni i zatvoreni. Uz to, većina JNDI metoda baca provjerene iznimke, za koje je potrebno dugo vrijeme. Pomnim pregledom čini se da se 50 do 60 posto vremena provedenog u programiranju JNDI troši na rješavanje ponavljajućih zadataka.

Spring LDAP je Java biblioteka otvorenog koda dizajnirana da pojednostavi LDAP programiranje na Java platformi. Baš kao što Spring Framework izvlači velik dio programiranja na niskoj razini iz razvoja Java Enterprise aplikacija, tako i Spring LDAP oslobađa infrastrukturnih detalja korištenja LDAP-a. Umjesto da brinete o NamingExceptions i dobivanju InitialContexts, možete se koncentrirati na poslovnu logiku svoje aplikacije. Spring LDAP također definira sveobuhvatnu neprovjerenu hijerarhiju izuzetaka i pruža pomoćne klase za izgradnju LDAP filtara i istaknutih imena.

Proljetni LDAP i JNDI

Imajte na umu da Spring LDAP okvir ne zamjenjuje JNDI. Umjesto toga, pruža klase omotača i uslužnih programa preko JNDI-a za pojednostavljivanje LDAP programiranja na Java platformi.

U ovom članku, početnom vodiču za korištenje Spring LDAP-a, započet ću razvijanjem jednostavnog JNDI programa za izvršavanje LDAP pretraživanja. Tada ću pokazati koliko je lakše učiniti istu stvar pomoću Spring LDAP okvira. Pokazat ću vam kako koristiti Spring LDAP- AttributeMapperove za mapiranje LDAP-ovih atributa na Java grah i kako koristiti njegove dinamičke filtre za izgradnju upita. Na kraju ću dati korak po korak uvod u upotrebu Spring LDAP okvira za dodavanje, brisanje i izmjenu podataka na vašem LDAP poslužitelju.

Imajte na umu da ovaj članak pretpostavlja da ste upoznati s konceptima i terminologijom Proljetnog okvira. Pogledajte odjeljak Resursi da biste saznali više o Spring Framework-u, LDAP-u i JNDI-u, kao i za preuzimanje uzorka aplikacije.

Jednostavan JNDI klijent

Popis 1 prikazuje jednostavan JNDI program koji će ispisati cn atribute svih Personvrsta objekata na vašoj konzoli.

Popis 1. SimpleLDAPClient.java

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) { } } } } }

Prvo što sam učinio na popisu 1 je stvaranje InitialDirContextobjekta koji se zatim koristi kao kontekst za sljedeće operacije direktorija. Prilikom stvaranja novog Contextobjekta konfiguriram svojstva poput korisničkog imena, lozinke i mehanizma provjere autentičnosti koja se mogu koristiti za povezivanje s LDAP poslužiteljem. Ja sam uspio to stvaranjem Hashtableobjekta, postavljanje svih tih svojstava kao ključ / vrijednost parova u Hashtablei polaganjem Hashtablena InitialDirContextkonstruktora.

Neposredni problem s ovim pristupom je taj što sam sve konfiguracijske parametre teško kodirao u datoteku .java. To dobro funkcionira za moj primjer, ali ne i za stvarnu aplikaciju. U stvarnoj aplikaciji želio bih pohraniti svojstva veze u datoteku jndi.properties i smjestiti je u put staze mog projekta ili u njegovu / lib mapu. Nakon stvaranja novog InitialDirContextobjekta, JNDI API tražit će na oba mjesta datoteku jndi.properties, a zatim je koristiti za stvaranje veze s LDAP poslužiteljem.

JNDI konfiguracijski parametri

Popis 2 prikazuje JNDI konfiguracijske parametre za povezivanje s mojim LDAP poslužiteljem. Objašnjavam značenje parametara u nastavku.

Popis 2. JNDI konfiguracijski parametri za LDAP

java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url=ldap://localhost:10389/ou=system java.naming.security.authentication=simple java.naming.security.principal=uid=admin,ou=system java.naming.security.credentials=secret
  1. Context.INITIAL_CONTEXT_FACTORY ( java.naming.factory.initial) trebao bi biti jednak potpuno kvalificiranom imenu klase koje će se koristiti za stvaranje novog početnog konteksta. Ako nije navedena vrijednost NoInitialContextException, baca se.
  2. Context.PROVIDER_URL ( java.naming.provider.url) trebao bi biti jednak URL-u LDAP poslužitelja s kojim se želite povezati. Trebao bi biti u formatu ldap://:.
  3. Context.SECURITY_AUTHENTICATION ( java.naming.security.authentication) predstavlja vrstu mehanizma za provjeru autentičnosti koji želite koristiti. U svom sam primjeru koristio korisničko ime i lozinku za provjeru autentičnosti, tako da je vrijednost ovog svojstva jednostavna .
  4. Context.SECURITY_PRINCIPAL ( java.naming.security.principal) predstavlja istaknuto korisničko ime (DN) koje treba koristiti za uspostavljanje veze.
  5. Context.SECURITY_CREDENTIALS ( java.naming.security.credentials) predstavlja korisničku lozinku.

Kôd JNDI klijenta

Nakon dobivanja Contextpredmeta moj sljedeći korak je stvaranje SearchControlobjekta koji obuhvaća čimbenike koji određuju opseg mog pretraživanja i ono što će se vratiti. Želim pretražiti cijelo podstablo ukorijenjeno u kontekstu, pa sam podesio opseg pretraživanja SUBTREE_SCOPEpozivajući setSearchScope()metodu SearchControl, kao što je prethodno prikazano u Popisu 1.

Next, I call the search() method of DirContext, passing in (objectclass=person) as the value of the filter. The search() method will return a NamingEnumeration object containing all the entries in the subtree of Context, where objectclass is equal to person. After getting a NamingEnumeration as my result object, I iterate through it and print a cn attribute for each Person object.

To dovršava moje objašnjenje JNDI klijentskog koda. Gledajući SimpleLDAPClient.java, prikazan u Popisu 1, lako možete vidjeti da više od polovice koda ide prema otvaranju i zatvaranju resursa. Još jedan problem s JNDI API-jem je taj što će većina njegovih metoda izbaciti jednu NamingExceptionili jednu od njegovih potklasa u slučaju pogreške. Budući da NamingExceptionje provjerena iznimka, morate je riješiti ako se baci, ali možete li se zaista oporaviti od iznimke ako vam LDAP poslužitelj ne radi? Ne, ne možeš.

Većina programera zaobilazi JNDI- NamingExceptionje tako što ih jednostavno uhvati i ne poduzima ništa. Problem s ovim rješenjem je taj što može uzrokovati gubitak važnih podataka.