001: // ========================================================================
002: // $Id: JAASUserRealm.java 1001 2006-09-23 09:31:51Z janb $
003: // Copyright 2003-2004 Mort Bay Consulting Pty. Ltd.
004: // ------------------------------------------------------------------------
005: // Licensed under the Apache License, Version 2.0 (the "License");
006: // you may not use this file except in compliance with the License.
007: // You may obtain a copy of the License at
008: // http://www.apache.org/licenses/LICENSE-2.0
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014: // ========================================================================
015:
016: package org.mortbay.jetty.plus.jaas;
017:
018: import java.security.Principal;
019: import java.security.acl.Group;
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.Set;
025:
026: import javax.security.auth.login.LoginContext;
027: import javax.security.auth.login.LoginException;
028:
029: import org.mortbay.jetty.Request;
030: import org.mortbay.jetty.plus.jaas.callback.AbstractCallbackHandler;
031: import org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler;
032: import org.mortbay.jetty.security.UserRealm;
033: import org.mortbay.log.Log;
034: import org.mortbay.util.Loader;
035:
036: /* ---------------------------------------------------- */
037: /** JAASUserRealm
038: * <p>
039: *
040: * <p><h4>Notes</h4>
041: * <p>
042: *
043: * <p><h4>Usage</h4>
044: *
045: *
046: *
047: *
048: * @org.apache.xbean.XBean element="jaasUserRealm" description="Creates a UserRealm suitable for use with JAAS"
049: */
050: public class JAASUserRealm implements UserRealm {
051: public static String DEFAULT_ROLE_CLASS_NAME = "org.mortbay.jetty.plus.jaas.JAASRole";
052: public static String[] DEFAULT_ROLE_CLASS_NAMES = { DEFAULT_ROLE_CLASS_NAME };
053:
054: protected String[] roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
055: protected String callbackHandlerClass;
056: protected String realmName;
057: protected String loginModuleName;
058: protected RoleCheckPolicy roleCheckPolicy;
059: protected JAASUserPrincipal defaultUser = new JAASUserPrincipal(
060: null, null);
061:
062: /* ---------------------------------------------------- */
063: /**
064: * Constructor.
065: *
066: */
067: public JAASUserRealm() {
068: }
069:
070: /* ---------------------------------------------------- */
071: /**
072: * Constructor.
073: *
074: * @param name the name of the realm
075: */
076: public JAASUserRealm(String name) {
077: this ();
078: realmName = name;
079: }
080:
081: /* ---------------------------------------------------- */
082: /**
083: * Get the name of the realm.
084: *
085: * @return name or null if not set.
086: */
087: public String getName() {
088: return realmName;
089: }
090:
091: /* ---------------------------------------------------- */
092: /**
093: * Set the name of the realm
094: *
095: * @param name a <code>String</code> value
096: */
097: public void setName(String name) {
098: realmName = name;
099: }
100:
101: /**
102: * Set the name to use to index into the config
103: * file of LoginModules.
104: *
105: * @param name a <code>String</code> value
106: */
107: public void setLoginModuleName(String name) {
108: loginModuleName = name;
109: }
110:
111: public void setCallbackHandlerClass(String classname) {
112: callbackHandlerClass = classname;
113: }
114:
115: public void setRoleClassNames(String[] classnames) {
116: ArrayList tmp = new ArrayList();
117:
118: if (classnames != null)
119: tmp.addAll(Arrays.asList(classnames));
120:
121: if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
122: tmp.add(DEFAULT_ROLE_CLASS_NAME);
123: roleClassNames = (String[]) tmp.toArray(new String[tmp.size()]);
124: }
125:
126: public String[] getRoleClassNames() {
127: return roleClassNames;
128: }
129:
130: public void setRoleCheckPolicy(RoleCheckPolicy policy) {
131: roleCheckPolicy = policy;
132: }
133:
134: //TODO: delete?!
135: public Principal getPrincipal(String username) {
136: return null;
137: }
138:
139: /* ------------------------------------------------------------ */
140: public boolean isUserInRole(Principal user, String role) {
141: JAASUserPrincipal thePrincipal = null;
142:
143: if (user == null)
144: thePrincipal = defaultUser;
145: else {
146: if (!(user instanceof JAASUserPrincipal))
147: return false;
148:
149: thePrincipal = (JAASUserPrincipal) user;
150: }
151: return ((JAASUserPrincipal) user).isUserInRole(role);
152: }
153:
154: /* ------------------------------------------------------------ */
155: public boolean reauthenticate(Principal user) {
156: if (user instanceof JAASUserPrincipal)
157: return true;
158: else
159: return false;
160: }
161:
162: /* ---------------------------------------------------- */
163: /**
164: * Authenticate a user.
165: *
166: *
167: * @param username provided by the user at login
168: * @param credentials provided by the user at login
169: * @param request a <code>Request</code> value
170: * @return authenticated JAASUserPrincipal or null if authenticated failed
171: */
172: public Principal authenticate(String username, Object credentials,
173: Request request) {
174: try {
175: AbstractCallbackHandler callbackHandler = null;
176:
177: //user has not been authenticated
178: if (callbackHandlerClass == null) {
179: Log
180: .warn("No CallbackHandler configured: using DefaultCallbackHandler");
181: callbackHandler = new DefaultCallbackHandler();
182: } else {
183: callbackHandler = (AbstractCallbackHandler) Loader
184: .loadClass(JAASUserRealm.class,
185: callbackHandlerClass).getConstructors()[0]
186: .newInstance(new Object[0]);
187: }
188:
189: if (callbackHandler instanceof DefaultCallbackHandler) {
190: ((DefaultCallbackHandler) callbackHandler)
191: .setRequest(request);
192: }
193:
194: callbackHandler.setUserName(username);
195: callbackHandler.setCredential(credentials);
196:
197: //set up the login context
198: LoginContext loginContext = new LoginContext(
199: loginModuleName, callbackHandler);
200:
201: loginContext.login();
202:
203: //login success
204: JAASUserPrincipal userPrincipal = new JAASUserPrincipal(
205: this , username);
206: userPrincipal.setSubject(loginContext.getSubject());
207: userPrincipal.setRoleCheckPolicy(roleCheckPolicy);
208: userPrincipal.setLoginContext(loginContext);
209:
210: return userPrincipal;
211: } catch (Exception e) {
212: Log.warn(e.toString());
213: Log.debug(e);
214: return null;
215: }
216: }
217:
218: /* ---------------------------------------------------- */
219: /**
220: * Removes any auth info associated with eg. the thread.
221: *
222: * @param user a UserPrincipal to disassociate
223: */
224: public void disassociate(Principal user) {
225: //TODO: should this apply to the default user?
226: if (user == null)
227: defaultUser.disassociate();
228: else
229: ((JAASUserPrincipal) user).disassociate();
230: }
231:
232: /* ---------------------------------------------------- */
233: /**
234: * Temporarily adds a role to a user.
235: *
236: * Temporarily granting a role pushes the role onto a stack
237: * of temporary roles. Temporary roles must therefore be
238: * removed in order.
239: *
240: * @param user the Principal to which to add the role
241: * @param role the role name
242: * @return the Principal with the role added
243: */
244: public Principal pushRole(Principal user, String role) {
245: JAASUserPrincipal thePrincipal = (JAASUserPrincipal) user;
246:
247: //use the default user
248: if (thePrincipal == null)
249: thePrincipal = defaultUser;
250:
251: thePrincipal.pushRole(role);
252: return thePrincipal;
253: }
254:
255: /* ------------------------------------------------------------ */
256: public Principal popRole(Principal user) {
257: JAASUserPrincipal thePrincipal = (JAASUserPrincipal) user;
258:
259: //use the default user
260: if (thePrincipal == null)
261: thePrincipal = defaultUser;
262:
263: thePrincipal.popRole();
264: return thePrincipal;
265: }
266:
267: public Group getRoles(JAASUserPrincipal principal) {
268: //get all the roles of the various types
269: String[] roleClassNames = getRoleClassNames();
270: Group roleGroup = new JAASGroup(JAASGroup.ROLES);
271:
272: try {
273: JAASUserPrincipal thePrincipal = principal;
274:
275: if (thePrincipal == null)
276: thePrincipal = defaultUser;
277:
278: for (int i = 0; i < roleClassNames.length; i++) {
279: Class load_class = Thread.currentThread()
280: .getContextClassLoader().loadClass(
281: roleClassNames[i]);
282: Set rolesForType = thePrincipal.getSubject()
283: .getPrincipals(load_class);
284: Iterator itor = rolesForType.iterator();
285: while (itor.hasNext()) {
286: roleGroup.addMember((Principal) itor.next());
287: }
288: }
289:
290: return roleGroup;
291: } catch (ClassNotFoundException e) {
292: throw new RuntimeException(e);
293: }
294: }
295:
296: /* ---------------------------------------------------- */
297: /**
298: * Logout a previously logged in user.
299: * This can only work for FORM authentication
300: * as BasicAuthentication is stateless.
301: *
302: * The user's LoginContext logout() method is called.
303: * @param user an <code>Principal</code> value
304: */
305: public void logout(Principal user) {
306: try {
307: JAASUserPrincipal authenticUser = null;
308:
309: if (user == null)
310: authenticUser = defaultUser; //TODO: should the default user ever be logged in?
311:
312: if (!(user instanceof JAASUserPrincipal))
313: throw new IllegalArgumentException(user
314: + " is not a JAASUserPrincipal");
315:
316: authenticUser = (JAASUserPrincipal) user;
317:
318: authenticUser.getLoginContext().logout();
319:
320: Log.debug(user + " has been LOGGED OUT");
321: } catch (LoginException e) {
322: Log.warn(e);
323: }
324: }
325:
326: }
|