KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > services > security > ldap > LDAPUserManager


1 package org.apache.turbine.services.security.ldap;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License")
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.util.List JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Vector JavaDoc;
22
23 import javax.naming.AuthenticationException JavaDoc;
24 import javax.naming.Context JavaDoc;
25 import javax.naming.NamingEnumeration JavaDoc;
26 import javax.naming.NamingException JavaDoc;
27 import javax.naming.directory.Attributes JavaDoc;
28 import javax.naming.directory.DirContext JavaDoc;
29 import javax.naming.directory.SearchControls JavaDoc;
30 import javax.naming.directory.SearchResult JavaDoc;
31
32 import org.apache.commons.configuration.Configuration;
33
34 import org.apache.torque.util.Criteria;
35
36 import org.apache.turbine.om.security.User;
37 import org.apache.turbine.services.security.TurbineSecurity;
38 import org.apache.turbine.services.security.UserManager;
39 import org.apache.turbine.util.security.DataBackendException;
40 import org.apache.turbine.util.security.EntityExistsException;
41 import org.apache.turbine.util.security.PasswordMismatchException;
42 import org.apache.turbine.util.security.UnknownEntityException;
43
44 /**
45  * A UserManager performs {@link org.apache.turbine.om.security.User}
46  * object related tasks on behalf of the
47  * {@link org.apache.turbine.services.security.SecurityService}.
48  *
49  * This implementation uses ldap for retrieving user data. It
50  * expects that the User interface implementation will be castable to
51  * {@link org.apache.turbine.om.BaseObject}.
52  *
53  * @author <a HREF="mailto:jon@collab.net">Jon S. Stevens</a>
54  * @author <a HREF="mailto:john.mcnally@clearink.com">John D. McNally</a>
55  * @author <a HREF="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
56  * @author <a HREF="mailto:cberry@gluecode.com">Craig D. Berry</a>
57  * @author <a HREF="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
58  * @author <a HREF="mailto:tadewunmi@gluecode.com">Tracy M. Adewunmi</a>
59  * @author <a HREF="mailto:lflournoy@gluecode.com">Leonard J. Flournoy</a>
60  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
61  * @author <a HREF="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
62  * @author <a HREF="mailto:hhernandez@itweb.com.mx">Humberto Hernandez</a>
63  * @version $Id: LDAPUserManager.java,v 1.14.2.3 2004/10/08 12:09:43 henning Exp $
64  */

65 public class LDAPUserManager implements UserManager
66 {
67     /**
68      * Initializes the UserManager
69      *
70      * @param conf A Configuration object to init this Manager
71      */

72     public void init(Configuration conf)
73     {
74         // GNDN
75
}
76
77     /**
78      * Check wether a specified user's account exists.
79      *
80      * The login name is used for looking up the account.
81      *
82      * @param user The user to be checked.
83      * @return true if the specified account exists
84      * @throws DataBackendException Error accessing the data backend.
85      */

86     public boolean accountExists(User user) throws DataBackendException
87     {
88         return accountExists(user.getName());
89     }
90
91     /**
92      *
93      * Check wether a specified user's account exists.
94      * The login name is used for looking up the account.
95      *
96      * @param username The name of the user to be checked.
97      * @return true if the specified account exists
98      * @throws DataBackendException Error accessing the data backend.
99      */

100     public boolean accountExists(String JavaDoc username)
101             throws DataBackendException
102     {
103         try
104         {
105             User ldapUser = retrieve(username);
106         }
107         catch (UnknownEntityException ex)
108         {
109             return false;
110         }
111
112         return true;
113     }
114
115     /**
116      * Retrieve a user from persistent storage using username as the
117      * key.
118      *
119      * @param username the name of the user.
120      * @return an User object.
121      * @exception UnknownEntityException if the user's account does not
122      * exist in the database.
123      * @exception DataBackendException Error accessing the data backend.
124      */

125     public User retrieve(String JavaDoc username)
126             throws UnknownEntityException, DataBackendException
127     {
128         try
129         {
130             DirContext JavaDoc ctx = bindAsAdmin();
131
132             /*
133              * Define the search.
134              */

135             String JavaDoc userBaseSearch = LDAPSecurityConstants.getBaseSearch();
136             String JavaDoc filter = LDAPSecurityConstants.getNameAttribute();
137
138             filter = "(" + filter + "=" + username + ")";
139
140             /*
141              * Create the default search controls.
142              */

143             SearchControls JavaDoc ctls = new SearchControls JavaDoc();
144
145             NamingEnumeration JavaDoc answer =
146                     ctx.search(userBaseSearch, filter, ctls);
147
148             if (answer.hasMore())
149             {
150                 SearchResult JavaDoc sr = (SearchResult JavaDoc) answer.next();
151                 Attributes JavaDoc attribs = sr.getAttributes();
152                 LDAPUser ldapUser = createLDAPUser();
153
154                 ldapUser.setLDAPAttributes(attribs);
155                 ldapUser.setTemp("turbine.user", ldapUser);
156
157                 return ldapUser;
158             }
159             else
160             {
161                 throw new UnknownEntityException("The given user: "
162                         + username + "\n does not exist.");
163             }
164         }
165         catch (NamingException JavaDoc ex)
166         {
167             throw new DataBackendException(
168                     "The LDAP server specified is unavailable", ex);
169         }
170     }
171
172     /**
173      * Retrieve a user from persistent storage using the primary key
174      *
175      * @param key The primary key object
176      * @return an User object.
177      * @throws UnknownEntityException if the user's record does not
178      * exist in the database.
179      * @throws DataBackendException if there is a problem accessing the
180      * storage.
181      */

182     public User retrieveById(Object JavaDoc key)
183             throws UnknownEntityException, DataBackendException
184     {
185         try
186         {
187             DirContext JavaDoc ctx = bindAsAdmin();
188
189             /*
190              * Define the search.
191              */

192             StringBuffer JavaDoc userBaseSearch = new StringBuffer JavaDoc();
193             userBaseSearch.append(LDAPSecurityConstants.getUserIdAttribute());
194             userBaseSearch.append("=");
195             userBaseSearch.append(String.valueOf(key));
196             userBaseSearch.append(",");
197             userBaseSearch.append(LDAPSecurityConstants.getBaseSearch());
198
199             /*
200              * Create the default search controls.
201              */

202             NamingEnumeration JavaDoc answer =
203                     ctx.search(userBaseSearch.toString(), (Attributes JavaDoc)null);
204
205             if (answer.hasMore())
206             {
207                 SearchResult JavaDoc sr = (SearchResult JavaDoc) answer.next();
208                 Attributes JavaDoc attribs = sr.getAttributes();
209                 LDAPUser ldapUser = createLDAPUser();
210
211                 ldapUser.setLDAPAttributes(attribs);
212                 ldapUser.setTemp("turbine.user", ldapUser);
213
214                 return ldapUser;
215             }
216             else
217             {
218                 throw new UnknownEntityException("No user exists for the key: "
219                         + String.valueOf(key) + "\n");
220             }
221         }
222         catch (NamingException JavaDoc ex)
223         {
224             throw new DataBackendException(
225                     "The LDAP server specified is unavailable", ex);
226         }
227     }
228
229     /**
230      * This is currently not implemented to behave as expected. It
231      * ignores the Criteria argument and returns all the users.
232      *
233      * Retrieve a set of users that meet the specified criteria.
234      *
235      * As the keys for the criteria, you should use the constants that
236      * are defined in {@link User} interface, plus the the names
237      * of the custom attributes you added to your user representation
238      * in the data storage. Use verbatim names of the attributes -
239      * without table name prefix in case of DB implementation.
240      *
241      * @param criteria The criteria of selection.
242      * @return a List of users meeting the criteria.
243      * @throws DataBackendException Error accessing the data backend.
244      * @deprecated Use <a HREF="#retrieveList">retrieveList</a> instead.
245      */

246     public User[] retrieve(Criteria criteria)
247             throws DataBackendException
248     {
249         return (User []) retrieveList(criteria).toArray(new User[0]);
250     }
251
252     /**
253      * Retrieve a list of users that meet the specified criteria.
254      *
255      * As the keys for the criteria, you should use the constants that
256      * are defined in {@link User} interface, plus the names
257      * of the custom attributes you added to your user representation
258      * in the data storage. Use verbatim names of the attributes -
259      * without table name prefix in case of Torque implementation.
260      *
261      * @param criteria The criteria of selection.
262      * @return a List of users meeting the criteria.
263      * @throws DataBackendException if there is a problem accessing the
264      * storage.
265      */

266     public List JavaDoc retrieveList(Criteria criteria)
267             throws DataBackendException
268     {
269         List JavaDoc users = new Vector JavaDoc(0);
270
271         try
272         {
273             DirContext JavaDoc ctx = bindAsAdmin();
274
275             String JavaDoc userBaseSearch = LDAPSecurityConstants.getBaseSearch();
276             String JavaDoc filter = LDAPSecurityConstants.getNameAttribute();
277
278             filter = "(" + filter + "=*)";
279
280             /*
281              * Create the default search controls.
282              */

283             SearchControls JavaDoc ctls = new SearchControls JavaDoc();
284
285             NamingEnumeration JavaDoc answer =
286                     ctx.search(userBaseSearch, filter, ctls);
287
288             while (answer.hasMore())
289             {
290                 SearchResult JavaDoc sr = (SearchResult JavaDoc) answer.next();
291                 Attributes JavaDoc attribs = sr.getAttributes();
292                 LDAPUser ldapUser = createLDAPUser();
293
294                 ldapUser.setLDAPAttributes(attribs);
295                 ldapUser.setTemp("turbine.user", ldapUser);
296                 users.add(ldapUser);
297             }
298         }
299         catch (NamingException JavaDoc ex)
300         {
301             throw new DataBackendException(
302                     "The LDAP server specified is unavailable", ex);
303         }
304         return users;
305     }
306
307     /**
308      * Retrieve a user from persistent storage using username as the
309      * key, and authenticate the user. The implementation may chose
310      * to authenticate to the server as the user whose data is being
311      * retrieved.
312      *
313      * @param username the name of the user.
314      * @param password the user supplied password.
315      * @return an User object.
316      * @exception PasswordMismatchException if the supplied password was
317      * incorrect.
318      * @exception UnknownEntityException if the user's account does not
319      * exist in the database.
320      * @exception DataBackendException Error accessing the data backend.
321      */

322     public User retrieve(String JavaDoc username, String JavaDoc password)
323             throws PasswordMismatchException,
324             UnknownEntityException, DataBackendException
325     {
326         User user = retrieve(username);
327
328         authenticate(user, password);
329         return user;
330     }
331
332     /**
333      * Save a User object to persistent storage. User's account is
334      * required to exist in the storage.
335      *
336      * @param user an User object to store.
337      * @throws UnknownEntityException if the user's account does not
338      * exist in the database.
339      * @throws DataBackendException if there is an LDAP error
340      *
341      */

342     public void store(User user)
343             throws UnknownEntityException, DataBackendException
344     {
345         if (!accountExists(user))
346         {
347             throw new UnknownEntityException("The account '"
348                     + user.getName() + "' does not exist");
349         }
350
351         try
352         {
353             LDAPUser ldapUser = (LDAPUser) user;
354             Attributes JavaDoc attrs = ldapUser.getLDAPAttributes();
355             String JavaDoc name = ldapUser.getDN();
356
357             DirContext JavaDoc ctx = bindAsAdmin();
358
359             ctx.modifyAttributes(name, DirContext.REPLACE_ATTRIBUTE, attrs);
360         }
361         catch (NamingException JavaDoc ex)
362         {
363             throw new DataBackendException("NamingException caught", ex);
364         }
365     }
366
367     /**
368      * This method is not yet implemented.
369      * Saves User data when the session is unbound. The user account is required
370      * to exist in the storage.
371      *
372      * LastLogin, AccessCounter, persistent pull tools, and any data stored
373      * in the permData hashtable that is not mapped to a column will be saved.
374      *
375      * @exception UnknownEntityException if the user's account does not
376      * exist in the database.
377      * @exception DataBackendException if there is a problem accessing the
378      * storage.
379      */

380     public void saveOnSessionUnbind(User user)
381             throws UnknownEntityException, DataBackendException
382     {
383         if (!accountExists(user))
384         {
385             throw new UnknownEntityException("The account '" +
386                     user.getName() + "' does not exist");
387         }
388     }
389
390     /**
391      * Authenticate a User with the specified password. If authentication
392      * is successful the method returns nothing. If there are any problems,
393      * exception was thrown.
394      *
395      * @param user a User object to authenticate.
396      * @param password the user supplied password.
397      * @exception PasswordMismatchException if the supplied password was
398      * incorrect.
399      * @exception UnknownEntityException if the user's account does not
400      * exist in the database.
401      * @exception DataBackendException Error accessing the data backend.
402      */

403     public void authenticate(User user, String JavaDoc password)
404             throws PasswordMismatchException,
405             UnknownEntityException,
406             DataBackendException
407     {
408         LDAPUser ldapUser = (LDAPUser) user;
409
410         try
411         {
412             bind(ldapUser.getDN(), password);
413         }
414         catch (AuthenticationException JavaDoc ex)
415         {
416             throw new PasswordMismatchException(
417                     "The given password for: "
418                     + ldapUser.getDN() + " is invalid\n");
419         }
420         catch (NamingException JavaDoc ex)
421         {
422             throw new DataBackendException(
423                     "NamingException caught:", ex);
424         }
425     }
426
427     /**
428      * This method is not yet implemented
429      * Change the password for an User.
430      *
431      * @param user an User to change password for.
432      * @param newPass the new password.
433      * @param oldPass the old password.
434      * @exception PasswordMismatchException if the supplied password was
435      * incorrect.
436      * @exception UnknownEntityException if the user's account does not
437      * exist in the database.
438      * @exception DataBackendException Error accessing the data backend.
439      */

440     public void changePassword(User user, String JavaDoc oldPass, String JavaDoc newPass)
441             throws PasswordMismatchException,
442             UnknownEntityException, DataBackendException
443     {
444         throw new DataBackendException(
445                 "The method changePassword has no implementation.");
446     }
447
448     /**
449      * This method is not yet implemented
450      * Forcibly sets new password for an User.
451      *
452      * This is supposed to be used by the administrator to change the forgotten
453      * or compromised passwords. Certain implementatations of this feature
454      * would require adminstrative level access to the authenticating
455      * server / program.
456      *
457      * @param user an User to change password for.
458      * @param password the new password.
459      * @exception UnknownEntityException if the user's record does not
460      * exist in the database.
461      * @exception DataBackendException Error accessing the data backend.
462      */

463     public void forcePassword(User user, String JavaDoc password)
464             throws UnknownEntityException, DataBackendException
465     {
466         throw new DataBackendException(
467                 "The method forcePassword has no implementation.");
468     }
469
470     /**
471      * Creates new user account with specified attributes.
472      *
473      * @param user the object describing account to be created.
474      * @param initialPassword Not used yet.
475      * @throws DataBackendException Error accessing the data backend.
476      * @throws EntityExistsException if the user account already exists.
477      */

478     public void createAccount(User user, String JavaDoc initialPassword)
479             throws EntityExistsException, DataBackendException
480     {
481         if (accountExists(user))
482         {
483             throw new EntityExistsException("The account '"
484                     + user.getName() + "' already exist");
485         }
486
487         try
488         {
489             LDAPUser ldapUser = (LDAPUser) user;
490             Attributes JavaDoc attrs = ldapUser.getLDAPAttributes();
491             String JavaDoc name = ldapUser.getDN();
492
493             DirContext JavaDoc ctx = bindAsAdmin();
494
495             ctx.bind(name, null, attrs);
496         }
497         catch (NamingException JavaDoc ex)
498         {
499             throw new DataBackendException("NamingException caught", ex);
500         }
501     }
502
503     /**
504      * Removes an user account from the system.
505      *
506      * @param user the object describing the account to be removed.
507      * @throws DataBackendException Error accessing the data backend.
508      * @throws UnknownEntityException if the user account is not present.
509      */

510     public void removeAccount(User user)
511             throws UnknownEntityException, DataBackendException
512     {
513         if (!accountExists(user))
514         {
515             throw new UnknownEntityException("The account '"
516                     + user.getName() + "' does not exist");
517         }
518
519         try
520         {
521             LDAPUser ldapUser = (LDAPUser) user;
522             String JavaDoc name = ldapUser.getDN();
523
524             DirContext JavaDoc ctx = bindAsAdmin();
525
526             ctx.unbind(name);
527         }
528         catch (NamingException JavaDoc ex)
529         {
530             throw new DataBackendException("NamingException caught", ex);
531         }
532     }
533
534     /**
535      * Bind as the admin user.
536      *
537      * @throws NamingException when an error occurs with the named server.
538      * @return a new DirContext.
539      */

540     public static DirContext JavaDoc bindAsAdmin()
541             throws NamingException JavaDoc
542     {
543         String JavaDoc adminUser = LDAPSecurityConstants.getAdminUsername();
544         String JavaDoc adminPassword = LDAPSecurityConstants.getAdminPassword();
545
546         return bind(adminUser, adminPassword);
547     }
548
549     /**
550      * Creates an initial context.
551      *
552      * @param username admin username supplied in TRP.
553      * @param password admin password supplied in TRP
554      * @throws NamingException when an error occurs with the named server.
555      * @return a new DirContext.
556      */

557     public static DirContext JavaDoc bind(String JavaDoc username, String JavaDoc password)
558             throws NamingException JavaDoc
559     {
560         String JavaDoc host = LDAPSecurityConstants.getLDAPHost();
561         String JavaDoc port = LDAPSecurityConstants.getLDAPPort();
562         String JavaDoc providerURL = new String JavaDoc("ldap://" + host + ":" + port);
563         String JavaDoc ldapProvider = LDAPSecurityConstants.getLDAPProvider();
564         String JavaDoc authentication = LDAPSecurityConstants.getLDAPAuthentication();
565
566         /*
567          * creating an initial context using Sun's client
568          * LDAP Provider.
569          */

570         Hashtable JavaDoc env = new Hashtable JavaDoc();
571
572         env.put(Context.INITIAL_CONTEXT_FACTORY, ldapProvider);
573         env.put(Context.PROVIDER_URL, providerURL);
574         env.put(Context.SECURITY_AUTHENTICATION, authentication);
575         env.put(Context.SECURITY_PRINCIPAL, username);
576         env.put(Context.SECURITY_CREDENTIALS, password);
577
578         DirContext JavaDoc ctx = new javax.naming.directory.InitialDirContext JavaDoc(env);
579
580         return ctx;
581     }
582
583     /**
584      * Create a new instance of the LDAP User according to the value
585      * configured in TurbineResources.properties.
586      * @return a new instance of the LDAP User.
587      * @throws DataBackendException if there is an error creating the
588      */

589     private LDAPUser createLDAPUser()
590             throws DataBackendException
591     {
592         try
593         {
594             return (LDAPUser) TurbineSecurity.getUserInstance();
595         }
596         catch (ClassCastException JavaDoc ex)
597         {
598             throw new DataBackendException("ClassCastException:", ex);
599         }
600         catch (UnknownEntityException ex)
601         {
602             throw new DataBackendException("UnknownEntityException:", ex);
603         }
604     }
605
606 }
607
Popular Tags