Προγραμματισμός

Απλοποιήστε την πρόσβαση στον κατάλογο με το Spring LDAP

Το Spring LDAP είναι ένα Spring-based πλαίσιο που απλοποιεί τον προγραμματισμό LDAP στην πλατφόρμα Java. Σε αυτόν τον βήμα προς βήμα οδηγό για τη χρήση του Spring LDAP θα μάθετε πώς το πλαίσιο χειρίζεται την κωδικοποίηση χαμηλού επιπέδου που απαιτείται από τους περισσότερους πελάτες LDAP, ώστε να μπορείτε να εστιάσετε στην ανάπτυξη της επιχειρηματικής λογικής της εφαρμογής σας. Θα ασκήσετε επίσης απλές λειτουργίες CRUD χρησιμοποιώντας το Spring LDAP και θα μάθετε για πιο προηγμένες λειτουργίες, όπως τη δημιουργία δυναμικών φίλτρων και τη μετατροπή καταχωρίσεων LDAP σε Java.

Το Lightweight Directory Access Protocol είναι ένα βασικό συστατικό των περισσότερων εταιρικών εφαρμογών μεγάλης κλίμακας σήμερα. Το LDAP χρησιμοποιείται κυρίως για την αποθήκευση πληροφοριών που σχετίζονται με την ταυτότητα χρήστη, όπως το όνομα χρήστη, τον κωδικό πρόσβασης και τη διεύθυνση ηλεκτρονικού ταχυδρομείου ενός χρήστη. Χρησιμοποιείται επίσης σε εφαρμογές ασφαλείας όπου είναι απαραίτητο να αποθηκεύσετε δικαιώματα πρόσβασης χρήστη για έλεγχο ταυτότητας και εξουσιοδότησης.

Java Naming and Directory Interface (JDNI) είναι το API που χρησιμοποιείται για προγραμματισμό LDAP στην πλατφόρμα Java. Ορίζει μια τυπική διεπαφή που μπορεί να χρησιμοποιηθεί στην εφαρμογή σας για να αλληλεπιδράσετε με οποιονδήποτε διακομιστή LDAP. Δυστυχώς, η χρήση του JNDI συνεπάγεται συνήθως τη σύνταξη πολλού επαναλαμβανόμενου κώδικα χαμηλού επιπέδου. Το JNDI κάνει πάρα πολλές εργασίες απλών διαδικασιών, όπως η εξασφάλιση ότι οι πόροι έχουν ανοίξει και κλείσει σωστά. Επιπλέον, οι περισσότερες μέθοδοι JNDI ρίχνουν ελεγμένες εξαιρέσεις, οι οποίες είναι χρονοβόρες για τη διαχείριση. Μετά από προσεκτική επιθεώρηση, φαίνεται ότι το 50 έως 60 τοις εκατό του χρόνου που αφιερώνεται στον προγραμματισμό JNDI είναι σπατάλη για τη διαχείριση επαναλαμβανόμενων εργασιών.

Το Spring LDAP είναι μια ανοιχτή βιβλιοθήκη Java που έχει σχεδιαστεί για να απλοποιεί τον προγραμματισμό LDAP στην πλατφόρμα Java. Ακριβώς όπως το Spring Framework παίρνει μεγάλο μέρος του προγραμματισμού χαμηλού επιπέδου από την ανάπτυξη εφαρμογών Java, το Spring LDAP σας απαλλάσσει από τις λεπτομέρειες υποδομής της χρήσης LDAP. Αντί να ανησυχείτε ΟνομασίαExceptionκαι να πάρει InitialContextΕίστε ελεύθεροι να επικεντρωθείτε στην επιχειρηματική λογική της εφαρμογής σας. Το Spring LDAP ορίζει επίσης μια ολοκληρωμένη μη ελεγχόμενη ιεραρχία εξαιρέσεων και παρέχει βοηθητικά μαθήματα για τη δημιουργία φίλτρων LDAP και διακεκριμένων ονομάτων.

Άνοιξη LDAP και JNDI

Σημειώστε ότι το πλαίσιο Spring LDAP δεν αντικαθιστά το JNDI. Αντίθετα, παρέχει τάξεις περιτυλίγματος και βοηθητικών προγραμμάτων μέσω του JNDI για απλοποίηση του προγραμματισμού LDAP στην πλατφόρμα Java.

Σε αυτό το άρθρο, έναν οδηγό για αρχάριους για τη χρήση του Spring LDAP, θα ξεκινήσω αναπτύσσοντας ένα απλό πρόγραμμα JNDI για την εκτέλεση μιας αναζήτησης LDAP. Στη συνέχεια θα δείξω πόσο πιο εύκολο είναι να κάνεις το ίδιο πράγμα χρησιμοποιώντας το πλαίσιο Spring LDAP. Θα σας δείξω πώς να χρησιμοποιείτε τα Spring LDAP's AttributeMappers για την αντιστοίχιση χαρακτηριστικών LDAP σε Java φασόλια και πώς να χρησιμοποιήσετε τα δυναμικά φίλτρα για τη δημιουργία ερωτημάτων. Τέλος, θα δώσω μια βήμα προς βήμα εισαγωγή στη χρήση του πλαισίου Spring LDAP για προσθήκη, διαγραφή και τροποποίηση δεδομένων στο διακομιστή LDAP σας.

Σημειώστε ότι αυτό το άρθρο προϋποθέτει ότι είστε εξοικειωμένοι με τις έννοιες και την ορολογία του Spring Framework. Ανατρέξτε στην ενότητα Πόροι για να μάθετε περισσότερα σχετικά με το Spring Framework, το LDAP και το JNDI, καθώς και για τη λήψη του δείγματος εφαρμογής.

Ένας απλός πελάτης JNDI

Η λίστα 1 δείχνει ένα απλό πρόγραμμα JNDI που θα εκτυπώσει το cn χαρακτηριστικά όλων των Πρόσωπο πληκτρολογήστε αντικείμενα στην κονσόλα σας.

Λίστα 1. SimpleLDAPClient.java

δημόσια τάξη 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, "απλό"); env.put (Context.SECURITY_PRINCIPAL, "uid = admin, ou = system"); env.put (Context.SECURITY_CREDENTIALS, "μυστικό"); DirContext ctx = null; Αποτελέσματα NamingEnumeration = null; δοκιμάστε το {ctx = νέο InitialDirContext (env); Έλεγχοι SearchControls = νέα SearchControls (); controls.setSearchScope (SearchControls.SUBTREE_SCOPE); αποτελέσματα = ctx.search ("", "(objectclass = person)", στοιχεία ελέγχου); ενώ (results.hasMore ()) {SearchResult searchResult = (SearchResult) results.next (); Χαρακτηριστικά γνωρίσματα = searchResult.getAttributes (); Χαρακτηριστικό attr = profiles.get ("cn"); String cn = (String) attr.get (); System.out.println ("Κοινό όνομα ατόμου =" + cn); }} catch (NamingException e) {ρίξτε νέο RuntimeException (e); } τελικά {if (αποτελέσματα! = null) {δοκιμάστε {results.close (); } catch (Εξαίρεση e) {}} if (ctx! = null) {δοκιμάστε {ctx.close (); } catch (Εξαίρεση ε) {}}}}}

Το πρώτο πράγμα που έχω κάνει στην Καταχώριση 1 είναι να δημιουργήσω ένα InitialDirContext αντικείμενο, το οποίο στη συνέχεια χρησιμοποιείται ως το πλαίσιο για τις ακόλουθες λειτουργίες καταλόγου. Κατά τη δημιουργία ενός νέου Συμφραζόμενα αντικείμενο I ρυθμίζω ιδιότητες όπως το όνομα χρήστη, τον κωδικό πρόσβασης και τον μηχανισμό ελέγχου ταυτότητας που μπορούν να χρησιμοποιηθούν για τη σύνδεση στο διακομιστή LDAP. Το κατάφερα δημιουργώντας ένα Hashtable αντικείμενο, ορίζοντας όλες αυτές τις ιδιότητες ως ζεύγη κλειδιών / τιμών στο Hashtable και περνώντας το Hashtable στο InitialDirContext κατασκευαστής.

Το άμεσο πρόβλημα με αυτήν την προσέγγιση είναι ότι έχω κωδικοποιήσει όλες τις παραμέτρους διαμόρφωσης σε ένα αρχείο .java. Αυτό λειτουργεί καλά για το παράδειγμά μου, αλλά όχι για μια πραγματική εφαρμογή. Σε μια πραγματική εφαρμογή θα ήθελα να αποθηκεύσω τις ιδιότητες σύνδεσης σε ένα αρχείο jndi.properties και να το τοποθετήσω είτε στο classpath του έργου μου είτε στον φάκελο / lib. Κατά τη δημιουργία ενός νέου InitialDirContext αντικείμενο, το JNDI API θα ψάξει και στα δύο αυτά μέρη για το αρχείο jndi.properties και, στη συνέχεια, θα το χρησιμοποιήσει για να δημιουργήσει μια σύνδεση με το διακομιστή LDAP.

Παράμετροι διαμόρφωσης JNDI

Η λίστα 2 δείχνει τις παραμέτρους διαμόρφωσης JNDI για σύνδεση με το διακομιστή LDAP μου. Εξηγώ την έννοια των παραμέτρων παρακάτω.

Λίστα 2. Παράμετροι διαμόρφωσης JNDI για LDAP

java.naming.factory.initial = com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url = ldap: // localhost: 10389 / ou = σύστημα java.naming.security.authentication = απλό java.naming.security .principal = uid = admin, ou = system java.naming.security.credentials = μυστικό
  1. Περιεχόμενο.INITIAL_CONTEXT_FACTORY (java.naming.factory.initial) πρέπει να είναι ίσο με το πλήρως αναγνωρισμένο όνομα κλάσης που θα χρησιμοποιηθεί για τη δημιουργία ενός νέου αρχικού περιβάλλοντος. Εάν δεν έχει καθοριστεί τιμή, τότε το NoInitialContextException ρίχνεται.
  2. Περιεχόμενο.PROVIDER_URL (java.naming.provider.url) πρέπει να ισούται με τη διεύθυνση URL του διακομιστή LDAP στον οποίο θέλετε να συνδεθείτε. Θα πρέπει να έχει τη μορφή ldap: //:.
  3. Περιεχόμενο.SECURITY_AUTHENTICATION (java.naming.security.authentication) αντιπροσωπεύει τον τύπο του μηχανισμού ελέγχου ταυτότητας που θέλετε να χρησιμοποιήσετε. Έχω χρησιμοποιήσει ένα όνομα χρήστη και έναν κωδικό πρόσβασης για έλεγχο ταυτότητας στο παράδειγμά μου, οπότε η αξία αυτής της ιδιότητας είναι απλός.
  4. Περιεχόμενο.SECURITY_PRINCIPAL (java.naming.security.principal) αντιπροσωπεύει το διακριτό όνομα χρήστη (DN) που πρέπει να χρησιμοποιηθεί για τη δημιουργία σύνδεσης.
  5. Περιεχόμενο.SECURITY_CREDENTIALS (java.naming.security.credentials) αντιπροσωπεύει τον κωδικό πρόσβασης του χρήστη.

Ο κωδικός πελάτη JNDI

Αφού πάρει το Συμφραζόμενα αντικείμενο το επόμενο βήμα μου είναι να δημιουργήσω ένα SearchControl αντικείμενο, το οποίο ενσωματώνει τους παράγοντες που καθορίζουν το εύρος της αναζήτησής μου και τι θα επιστραφεί. Θέλω να κάνω αναζήτηση σε ολόκληρο το δευτερεύον δέντρο ριζωμένο στο περιβάλλον, οπότε έχω ορίσει το πεδίο αναζήτησης SUBTREE_SCOPE καλώντας το setSearchScope () μέθοδος για SearchControl, όπως φαίνεται προηγουμένως στην καταχώριση 1.

Στη συνέχεια, αποκαλώ το Αναζήτηση() μέθοδος για DirContext, περνώντας μέσα (αντικείμενο κλάσης = άτομο) ως η τιμή του φίλτρου. ο Αναζήτηση() η μέθοδος θα επιστρέψει a ΟνομασίαEnumeration αντικείμενο που περιέχει όλες τις καταχωρήσεις στο υποδένδρο του Συμφραζόμενα, όπου αντικείμενο κλάσης είναι ίσο με πρόσωπο. Αφού αποκτήσετε ένα ΟνομασίαEnumeration ως αντικείμενο αποτελέσματος, επαναλαμβάνω και εκτυπώνω ένα cn χαρακτηριστικό για καθένα Πρόσωπο αντικείμενο.

Αυτό συμπληρώνει την εξήγησή μου για τον κωδικό πελάτη JNDI. Κοιτάζοντας το SimpleLDAPClient.java, που εμφανίζεται στην καταχώριση 1, μπορείτε εύκολα να δείτε ότι περισσότερο από το ήμισυ του κώδικα πηγαίνει προς το άνοιγμα και το κλείσιμο πόρων. Ένα άλλο πρόβλημα με το JNDI API είναι ότι οι περισσότερες από τις μεθόδους του θα ρίξουν ένα ΟνομασίαException ή μία από τις υποκατηγορίες του σε περίπτωση σφάλματος. Επειδή ΟνομασίαException είναι μια ελεγμένη εξαίρεση, πρέπει να τη χειριστείτε εάν ρίξει, αλλά μπορείτε πραγματικά να ανακτήσετε από μια εξαίρεση εάν ο διακομιστής LDAP σας είναι εκτός λειτουργίας; Όχι, δεν μπορείς.

Οι περισσότεροι προγραμματιστές μετακινούνται στο JNDI ΟνομασίαExceptionαπλώς τους πιάνει και δεν κάνει τίποτα. Το πρόβλημα με αυτήν τη λύση είναι ότι μπορεί να σας κάνει να χάσετε σημαντικές πληροφορίες.