KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > appserv > security > AppservPasswordLoginModule


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.appserv.security;
25
26 import java.util.*;
27 import java.util.logging.Logger JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import com.sun.logging.LogDomains;
30 import com.sun.enterprise.util.i18n.StringManager;
31 import javax.security.auth.*;
32 import javax.security.auth.callback.*;
33 import javax.security.auth.login.*;
34 import javax.security.auth.spi.*;
35 import com.sun.enterprise.deployment.PrincipalImpl;
36 import com.sun.enterprise.deployment.Group;
37 import com.sun.enterprise.security.auth.realm.Realm;
38 import com.sun.enterprise.security.auth.login.PasswordCredential;
39 import com.sun.web.security.PrincipalGroupFactory;
40
41
42 /**
43  * Abstract base class for password-based login modules.
44  *
45  * <P>Most login modules receive a username and password from the client
46  * (possibly through HTTP BASIC auth, or FORM, or other mechanism) and
47  * then make (or delegate) an authentication decision based on this data.
48  * This class provides common methods for such password-based login modules.
49  *
50  * <P>Subclasses need to implement the authenticate() method and later
51  * call commitAuthentication().
52  *
53  */

54 public abstract class AppservPasswordLoginModule implements LoginModule
55 {
56     // The _subject, _sharedState and _options satisfy LoginModule and are
57
// shared across sub-classes
58
protected Subject _subject;
59     protected Map _sharedState;
60     protected Map _options;
61     
62     protected String JavaDoc _username;
63     protected String JavaDoc _password;
64     protected Realm _currentRealm;
65     
66     // the authentication status
67
protected boolean _succeeded = false;
68     protected boolean _commitSucceeded = false;
69     protected PrincipalImpl _userPrincipal;
70     protected String JavaDoc[] _groupsList = null;
71
72     protected Logger JavaDoc _logger =
73         LogDomains.getLogger(LogDomains.SECURITY_LOGGER);
74
75     protected final static StringManager sm =
76         StringManager.getManager("com.sun.enterprise.security.auth.login");
77
78     
79     /**
80      * Initialize this login module.
81      *
82      * @param subject - the Subject to be authenticated.
83      * @param callbackHandler - a CallbackHandler for obtaining the subject
84      * username and password.
85      * @param sharedState - state shared with other configured LoginModules.
86      * @param options - options specified in the login Configuration for
87      * this particular LoginModule.
88      *
89      */

90     final public void initialize(Subject subject, CallbackHandler callbackHandler,
91                            Map sharedState, Map options)
92     {
93         _subject = subject;
94         _sharedState = sharedState;
95         _options = options;
96         if(_logger.isLoggable(Level.FINE)){
97             _logger.log(Level.FINE, "Login module initialized: "+
98                            this.getClass().toString());
99         }
100     }
101
102
103     /**
104      * Perform login.
105      *
106      * <P>The callback handler is used to obtain authentication info
107      * for the subject and a login is attempted. This PasswordLoginModule
108      * expects to find a PasswordCredential in the private credentials
109      * of the Subject. If not present the login fails. The callback
110      * handler is ignored as it is not really relevant on the server side.
111      * Finally, the authenticate() method is invoked.
112      *
113      * @returns true if login succeeds, otherwise an exception is thrown.
114      * @throws LoginException Thrown if login failed, or on other problems.
115      *
116      */

117     final public boolean login() throws LoginException
118     {
119         if (_subject==null) {
120             String JavaDoc msg = sm.getString("pwdlm.noinfo");
121             _logger.log(Level.SEVERE, msg);
122             throw new LoginException(msg);
123         }
124
125         PasswordCredential pwdCred = null;
126
127         try {
128             Iterator i = _subject.getPrivateCredentials().iterator();
129             while (i.hasNext() && pwdCred==null) {
130                 Object JavaDoc privCred = i.next();
131                 if (privCred instanceof PasswordCredential) {
132                     pwdCred = (PasswordCredential)privCred;
133                 }
134             }
135         } catch (Exception JavaDoc e) {
136             _logger.log(Level.WARNING, "passwordlm.nocreds", e.toString());
137         }
138
139         if (pwdCred==null) {
140             _logger.log(Level.SEVERE, "passwordlm.nopwdcred");
141             String JavaDoc msg = sm.getString("pwdlm.nocreds");
142             throw new LoginException(msg);
143         }
144
145         // Need to obtain the requested realm to get parameters.
146

147         String JavaDoc realm = null;
148         try {
149             realm = pwdCred.getRealm();
150             _currentRealm = Realm.getInstance(realm);
151
152         } catch (Exception JavaDoc e) {
153             String JavaDoc msg = sm.getString("pwdlm.norealm", realm);
154             _logger.log(Level.SEVERE, msg);
155             throw new LoginException(msg);
156         }
157
158         if (_currentRealm == null) {
159             String JavaDoc msg = sm.getString("pwdlm.norealmavail", realm);
160             _logger.log(Level.SEVERE, msg);
161             throw new LoginException(msg);
162         }
163
164         // Get username and password data from credential (ignore callback)
165

166         _username = pwdCred.getUser();
167         _password = pwdCred.getPassword();
168
169         // Delegate the actual authentication to subclass.
170

171         authenticateUser();
172         if(_logger.isLoggable(Level.FINE)){
173             _logger.log(Level.FINE, "JAAS login complete.");
174         }
175         return true;
176     }
177
178     
179     /**
180      * Commit the authentication.
181      *
182      * <P>Commit is called after all necessary login modules have succeeded.
183      * It adds (if not present) a PrincipalImpl principal and a
184      * LocalCredentials public credential to the Subject.
185      *
186      * @throws LoginException If commit fails.
187      *
188      */

189     public boolean commit() throws LoginException
190     {
191         if (_succeeded == false) {
192             return false;
193         }
194
195         // Add a Principal (authenticated identity) to the Subject
196
// Assume the user we authenticated is the PrincipalImpl [RI]
197
String JavaDoc realm_name = _currentRealm.getName();
198         _userPrincipal =
199             PrincipalGroupFactory.getPrincipalInstance(_username, realm_name);
200         Set principalSet = _subject.getPrincipals();
201         if (!principalSet.contains(_userPrincipal)){
202             principalSet.add(_userPrincipal);
203         }
204         /* populate the group in the subject and clean out the slate at the same
205          * time
206          */

207         for(int i = 0; i<_groupsList.length; i++){
208             if(_groupsList[i] != null){
209                 Group g =
210                     PrincipalGroupFactory.getGroupInstance(_groupsList[i], realm_name);
211                 if(!principalSet.contains(g)){
212                     principalSet.add(g);
213                 }
214                 
215                 // cleaning the slate
216
_groupsList[i] = null;
217             }
218         }
219         
220         // In any case, clean out state.
221
_groupsList = null;
222         _username = null;
223         _password = null;
224         _commitSucceeded = true;
225         if(_logger.isLoggable(Level.FINE)){
226             _logger.log(Level.FINE,"JAAS authentication committed.");
227         }
228         return true;
229     }
230
231
232     /**
233      * Abort the authentication process.
234      *
235      */

236     final public boolean abort() throws LoginException
237     {
238         if(_logger.isLoggable(Level.FINE)){
239             _logger.log(Level.FINE,"JAAS authentication aborted.");
240         }
241         
242         if (_succeeded == false) {
243             return false;
244         } else if (_succeeded == true && _commitSucceeded == false) {
245             // login succeeded but overall authentication failed
246
_succeeded = false;
247             _username = null;
248             _password = null;
249             _userPrincipal = null;
250             for(int i = 0; i < _groupsList.length; i++){
251                 _groupsList[i] = null;
252             }
253             _groupsList = null;
254         } else {
255             // overall authentication succeeded and commit succeeded,
256
// but someone else's commit failed
257
logout();
258         }
259         return true;
260     }
261
262
263     /**
264      * Log out the subject.
265      *
266      */

267     final public boolean logout() throws LoginException
268     {
269         if(_logger.isLoggable(Level.FINE)){
270             _logger.log(Level.FINE, "JAAS logout for: " + _subject.toString());
271         }
272         
273         _subject.getPrincipals().remove(_userPrincipal);
274
275         _succeeded = false;
276         _succeeded = _commitSucceeded;
277         _username = null;
278         _password = null;
279         _userPrincipal = null;
280         if(_groupsList != null){
281             for (int i = 0; i < _groupsList.length; i++){
282                 _groupsList[i] = null;
283             }
284             _groupsList = null;
285         }
286         return true;
287     }
288
289     
290     /**
291      *
292      * <P>This is a convenience method which can be used by subclasses
293      *
294      * <P>Note that this method is called after the authentication
295      * has succeeded. If authentication failed do not call this method.
296      *
297      * Global instance field succeeded is set to true by this method.
298      *
299      * @param groups String array of group memberships for user (could be
300      * empty).
301      */

302     public final void commitUserAuthentication (final String JavaDoc[] groups)
303     {
304         _groupsList = groups;
305         _succeeded = true;
306     }
307
308     /**
309      * @return the subject being authenticated.
310      * use case:
311      * A custom login module could overwrite commit() method, and call getSubject()
312      * to get subject being authenticated inside its commit(). Custom principal
313      * then can be added to subject. By doing this,custom principal will be stored
314      * in calling thread's security context and participate in following Appserver's
315      * authorization.
316      *
317      */

318     public Subject getSubject()
319     {
320         return _subject;
321     }
322     
323     /**
324      * Perform authentication decision.
325      *
326      * Method returns silently on success and returns a LoginException
327      * on failure.
328      * @throws LoginException on authentication failure.
329      *
330      */

331     abstract protected void authenticateUser() throws LoginException;
332 }
333
Popular Tags