Sederhanakan akses direktori dengan Spring LDAP

Spring LDAP adalah framework berbasis Spring yang menyederhanakan pemrograman LDAP di platform Java. Dalam panduan langkah demi langkah untuk menggunakan Spring LDAP ini, Anda akan mempelajari bagaimana framework menangani pengkodean tingkat rendah yang diperlukan oleh sebagian besar klien LDAP, sehingga Anda dapat fokus pada pengembangan logika bisnis aplikasi Anda. Anda juga akan mempraktikkan operasi CRUD sederhana menggunakan Spring LDAP dan mempelajari tentang operasi lebih lanjut seperti membuat filter dinamis dan mengubah entri LDAP menjadi kacang Java.

Protokol Akses Direktori Ringan adalah komponen penting dari sebagian besar penerapan aplikasi perusahaan berskala besar saat ini. LDAP terutama digunakan untuk menyimpan informasi yang berkaitan dengan identitas pengguna, seperti nama pengguna, kata sandi, dan alamat email pengguna. Ini juga digunakan dalam implementasi keamanan di mana perlu untuk menyimpan hak akses pengguna untuk tujuan otentikasi dan otorisasi.

Java Naming and Directory Interface (JDNI) adalah API yang digunakan untuk pemrograman LDAP pada platform Java. Ini mendefinisikan antarmuka standar yang dapat digunakan dalam aplikasi Anda untuk berinteraksi dengan server LDAP apa pun. Sayangnya, menggunakan JNDI biasanya memerlukan penulisan kode berulang tingkat rendah. JNDI membuat terlalu banyak pekerjaan prosedur sederhana, seperti memastikan bahwa sumber daya telah dibuka dan ditutup dengan benar. Selain itu, sebagian besar metode JNDI menampilkan pengecualian yang diperiksa, yang memakan waktu untuk ditangani. Setelah diperiksa dengan cermat, tampaknya 50 hingga 60 persen waktu yang dihabiskan untuk pemrograman JNDI terbuang percuma untuk menangani tugas yang berulang.

Spring LDAP adalah pustaka Java open source yang dirancang untuk menyederhanakan pemrograman LDAP pada platform Java. Sama seperti Spring Framework mengambil banyak program tingkat rendah dari pengembangan aplikasi perusahaan Java, Spring LDAP membebaskan Anda dari detail infrastruktur penggunaan LDAP. Daripada mengkhawatirkan tentang NamingExceptiondan mendapatkan InitialContext, Anda bebas berkonsentrasi pada logika bisnis aplikasi Anda. Spring LDAP juga mendefinisikan hierarki pengecualian lengkap yang tidak dicentang dan menyediakan kelas pembantu untuk membuat filter LDAP dan nama yang dibedakan.

LDAP musim semi dan JNDI

Perhatikan bahwa kerangka kerja Spring LDAP tidak menggantikan JNDI. Sebaliknya, ia menyediakan kelas pembungkus dan utilitas melalui JNDI untuk menyederhanakan pemrograman LDAP di platform Java.

Pada artikel ini, panduan pemula untuk menggunakan Spring LDAP, saya akan mulai dengan mengembangkan program JNDI sederhana untuk menjalankan pencarian LDAP. Saya kemudian akan mendemonstrasikan betapa lebih mudahnya melakukan hal yang sama menggunakan framework Spring LDAP. Saya akan menunjukkan cara menggunakan Spring LDAP AttributeMapperuntuk memetakan atribut LDAP ke kacang Java, dan cara menggunakan filter dinamisnya untuk membangun kueri. Terakhir, saya akan memberikan pengantar langkah demi langkah untuk menggunakan framework Spring LDAP untuk menambah, menghapus, dan mengubah data di server LDAP Anda.

Perhatikan bahwa artikel ini menganggap Anda sudah familiar dengan konsep dan terminologi Spring Framework. Lihat bagian Sumber Daya untuk mempelajari lebih lanjut tentang Spring Framework, LDAP dan JNDI serta untuk mengunduh aplikasi sampel.

Klien JNDI sederhana

Kode 1 menunjukkan program JNDI sederhana yang akan mencetak atribut cn dari semua Personobjek tipe di konsol Anda.

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

Hal pertama yang saya lakukan dalam Listing 1 adalah membuat sebuah InitialDirContextobjek, yang kemudian digunakan sebagai konteks untuk operasi direktori berikut. Saat membuat Contextobjek baru, saya mengonfigurasi properti seperti nama pengguna, sandi, dan mekanisme autentikasi yang dapat digunakan untuk menyambung ke server LDAP. Saya telah mengatur ini dengan membuat Hashtableobjek, menyiapkan semua properti ini sebagai pasangan kunci / nilai di Hashtabledan meneruskan Hashtableke InitialDirContextkonstruktor.

Masalah langsung dengan pendekatan ini adalah saya telah melakukan hard-code semua parameter konfigurasi ke dalam file .java. Ini berfungsi dengan baik untuk contoh saya, tetapi tidak untuk aplikasi dunia nyata. Dalam aplikasi dunia nyata saya ingin menyimpan properti koneksi dalam file jndi.properties dan menempatkan file itu di classpath proyek saya atau folder / libnya. Setelah membuat InitialDirContextobjek baru , JNDI API akan mencari file jndi.properties di kedua tempat tersebut, lalu menggunakannya untuk membuat sambungan ke server LDAP.

Parameter konfigurasi JNDI

Kode 2 menunjukkan parameter konfigurasi JNDI untuk menghubungkan ke server LDAP saya. Saya menjelaskan arti parameter di bawah ini.

Kode 2. Parameter konfigurasi JNDI untuk 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) harus sama dengan nama kelas yang memenuhi syarat yang akan digunakan untuk membuat konteks awal baru. Jika tidak ada nilai yang ditentukan maka NoInitialContextExceptiondilempar.
  2. Context.PROVIDER_URL ( java.naming.provider.url) harus sama dengan URL server LDAP yang ingin Anda sambungkan. Ini harus dalam format ldap://:.
  3. Context.SECURITY_AUTHENTICATION ( java.naming.security.authentication) mewakili jenis mekanisme otentikasi yang ingin Anda gunakan. Saya telah menggunakan nama pengguna dan kata sandi untuk otentikasi dalam contoh saya, jadi nilai properti ini sederhana .
  4. Context.SECURITY_PRINCIPAL ( java.naming.security.principal) mewakili nama pengguna (DN) dibedakan yang harus digunakan untuk membuat sambungan.
  5. Context.SECURITY_CREDENTIALS ( java.naming.security.credentials) mewakili sandi pengguna.

Kode klien JNDI

Setelah mendapatkan Contextobjek, langkah saya selanjutnya adalah membuat SearchControlobjek, yang merangkum faktor-faktor yang menentukan cakupan pencarian saya dan apa yang akan dikembalikan. Saya ingin mencari seluruh subpohon yang berakar pada konteksnya, jadi saya mengatur ruang lingkup pencarian SUBTREE_SCOPEdengan memanggil setSearchScope()metode SearchControl, seperti yang ditunjukkan sebelumnya pada Daftar 1.

Selanjutnya, saya memanggil search()metode DirContext, meneruskan (objectclass=person)sebagai nilai filter. The search()metode akan mengembalikan NamingEnumerationobjek yang berisi semua entri dalam subtree dari Context, di mana objectclasssama dengan person. Setelah mendapatkan NamingEnumerationsebagai objek hasil, saya mengulanginya dan mencetak atribut cn untuk setiap Personobjek.

Itu melengkapi penjelasan saya tentang kode klien JNDI. Melihat SimpleLDAPClient.java, yang ditunjukkan pada Listing 1, Anda dapat dengan mudah melihat bahwa lebih dari setengah kode digunakan untuk membuka dan menutup sumber daya. Masalah lain dengan JNDI API adalah sebagian besar metodenya akan membuang satu NamingExceptionatau salah satu subkelasnya jika terjadi kesalahan. Karena NamingExceptionmerupakan pengecualian yang dicentang, Anda harus menanganinya jika dilempar, tetapi dapatkah Anda benar-benar memulihkan dari pengecualian jika server LDAP Anda tidak aktif? Tidak boleh.

Sebagian besar pengembang menyiasati JNDI NamingExceptionhanya dengan menangkapnya dan tidak melakukan apa pun. Masalah dengan solusi ini adalah dapat menyebabkan Anda kehilangan informasi penting.