KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > security > JetspeedDBSecurityService


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

16
17 package org.apache.jetspeed.services.security;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23
24 import javax.servlet.ServletConfig JavaDoc;
25
26 import org.apache.jetspeed.om.security.JetspeedUser;
27 import org.apache.jetspeed.om.security.JetspeedUserFactory;
28 import org.apache.jetspeed.om.security.UserNamePrincipal;
29 import org.apache.jetspeed.portal.Portlet;
30 import org.apache.jetspeed.services.JetspeedPortalAccessController;
31 import org.apache.jetspeed.services.JetspeedSecurity;
32 import org.apache.jetspeed.services.JetspeedUserManagement;
33 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
34 import org.apache.jetspeed.services.logging.JetspeedLogger;
35 import org.apache.jetspeed.services.rundata.JetspeedRunData;
36 import org.apache.turbine.om.security.User;
37 import org.apache.turbine.services.InitializationException;
38 import org.apache.turbine.services.TurbineBaseService;
39 import org.apache.turbine.services.TurbineServices;
40 import org.apache.turbine.services.resources.ResourceService;
41
42 /**
43  * <p>This is an implementation of the <code>JetspeedSecurityService</code> interface.
44  *
45  *
46  * @author <a HREF="mailto:david@bluesunrise.com">David Sean Taylor</a>
47  * @author <a HREF="mailto:sgala@hisitech.com">Santiago Gala</a>
48  * @version $Id: JetspeedDBSecurityService.java,v 1.25 2004/03/31 04:49:10 morciuch Exp $
49  */

50
51 public class JetspeedDBSecurityService extends TurbineBaseService
52                                        implements JetspeedSecurityService
53 {
54     /**
55      * Static initialization of the logger for this class
56      */

57     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedDBSecurityService.class.getName());
58     
59     private final static String JavaDoc CONFIG_CASEINSENSITIVE_USERNAME = "caseinsensitive.username";
60     private final static String JavaDoc CONFIG_CASEINSENSITIVE_PASSWORD = "caseinsensitive.password";
61     private final static String JavaDoc CONFIG_CASEINSENSITIVE_UPPER = "caseinsensitive.upper";
62     private final static String JavaDoc CONFIG_LOGON_STRIKE_COUNT = "logon.strike.count";
63     private final static String JavaDoc CONFIG_LOGON_STRIKE_MAX = "logon.strike.max";
64     private final static String JavaDoc CONFIG_LOGON_STRIKE_INTERVAL = "logon.strike.interval";
65     private final static String JavaDoc CONFIG_LOGON_AUTO_DISABLE = "logon.auto.disable";
66     private final static String JavaDoc CONFIG_ACTIONS_ANON_DISABLE = "actions.anon.disable";
67     private final static String JavaDoc CONFIG_ACTIONS_ALLUSERS_DISABLE = "actions.allusers.disable";
68     private final static String JavaDoc CONFIG_ACTIONS_ADMIN_ROLES = "admin.roles";
69
70     private final static String JavaDoc CONFIG_NEWUSER_ROLES = "newuser.roles";
71     private final static String JavaDoc CONFIG_DEFAULT_PERMISSION_LOGGEDIN = "permission.default.loggedin";
72     private final static String JavaDoc CONFIG_DEFAULT_PERMISSION_ANONYMOUS = "permission.default.anonymous";
73     private final static String JavaDoc CONFIG_ANONYMOUS_USER = "user.anonymous";
74     private final static String JavaDoc [] DEFAULT_PERMISSIONS = {""};
75     private final static String JavaDoc [] DEFAULT_CONFIG_NEWUSER_ROLES =
76     { "user" };
77     private final static String JavaDoc [] DEFAULT_ADMIN_ROLES =
78     { "admin" };
79
80     String JavaDoc roles[] = null;
81     boolean caseInsensitiveUsername = false;
82     boolean caseInsensitivePassword = false;
83     boolean caseInsensitiveUpper = true;
84     boolean actionsAnonDisable = true;
85     boolean actionsAllUsersDisable = false;
86     String JavaDoc anonymousUser = "anon";
87     String JavaDoc[] adminRoles = null;
88
89     int strikeCount = 3; // 3 within the interval
90
int strikeMax = 20; // 20 total failures
91
long strikeInterval = 300; // five minutes
92

93     boolean autoLogonDisable = false;
94
95     private static HashMap JavaDoc users = new HashMap JavaDoc();
96
97     private static Object JavaDoc sem = new Object JavaDoc();
98
99     /**
100      * This is the early initialization method called by the
101      * Turbine <code>Service</code> framework
102      * @param conf The <code>ServletConfig</code>
103      * @exception throws a <code>InitializationException</code> if the service
104      * fails to initialize
105      */

106     public synchronized void init(ServletConfig JavaDoc conf) throws InitializationException
107     {
108         // already initialized
109
if (getInit()) return;
110
111         super.init(conf);
112
113         // get configuration parameters from Jetspeed Resources
114
ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
115                                                      .getResources(JetspeedSecurityService.SERVICE_NAME);
116         
117         try
118         {
119             roles = serviceConf.getStringArray(CONFIG_NEWUSER_ROLES);
120             adminRoles = serviceConf.getStringArray(CONFIG_ACTIONS_ADMIN_ROLES);
121         }
122         catch (Exception JavaDoc e)
123         {}
124             
125         if (null == roles || roles.length == 0)
126         {
127             roles = DEFAULT_CONFIG_NEWUSER_ROLES;
128         }
129
130         if (null == adminRoles || adminRoles.length == 0)
131         {
132             adminRoles = DEFAULT_ADMIN_ROLES;
133         }
134
135         caseInsensitiveUsername = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_USERNAME, caseInsensitiveUsername);
136         caseInsensitivePassword = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_PASSWORD, caseInsensitivePassword);
137         caseInsensitiveUpper = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_UPPER, caseInsensitiveUpper);
138
139         strikeCount = serviceConf.getInt(CONFIG_LOGON_STRIKE_COUNT, strikeCount);
140         strikeInterval = serviceConf.getLong(CONFIG_LOGON_STRIKE_INTERVAL, strikeInterval);
141         strikeMax = serviceConf.getInt(CONFIG_LOGON_STRIKE_MAX, strikeMax);
142
143         autoLogonDisable = serviceConf.getBoolean(CONFIG_LOGON_AUTO_DISABLE, autoLogonDisable);
144         actionsAnonDisable = serviceConf.getBoolean(CONFIG_ACTIONS_ANON_DISABLE, actionsAnonDisable);
145         actionsAllUsersDisable = serviceConf.getBoolean(CONFIG_ACTIONS_ALLUSERS_DISABLE, actionsAllUsersDisable);
146
147         anonymousUser = serviceConf.getString(CONFIG_ANONYMOUS_USER, anonymousUser);
148
149         // initialization done
150
setInit(true);
151      }
152
153
154     //////////////////////////////////////////////////////////////////////////
155
//
156
// Required JetspeedSecurity Functions
157
//
158
// Required Features provided by default JetspeedSecurity
159
//
160
//////////////////////////////////////////////////////////////////////////
161

162     /*
163      * Factory to create a new JetspeedUser, using JetspeedUserFactory.
164      * The class that is created by the default JetspeedUserFactory is configured
165      * in the JetspeedSecurity properties:
166      *
167      * services.JetspeedSecurity.user.class=
168      * org.apache.jetspeed.om.security.BaseJetspeedUser
169      *
170      * @return JetspeedUser a newly created user that implements JetspeedUser.
171      */

172     public JetspeedUser getUserInstance()
173     {
174         try
175         {
176             return JetspeedUserFactory.getInstance();
177         }
178         catch (UserException e)
179         {
180             return null;
181         }
182     }
183
184     //////////////////////////////////////////////////////////////////////////
185
//
186
// Optional JetspeedSecurity Features
187
//
188
// Features are not required to be implemented by Security Provider
189
//
190
//////////////////////////////////////////////////////////////////////////
191

192     /*
193      * During logon, the username can be case sensitive or case insensitive.
194      *
195      * Given a username, converts the username to either lower or upper case.
196      * This optional feature is configurable from the JetspeedSecurity.properties:
197      *
198      * <code>services.JetspeedSecurity.caseinsensitive.username = true/false</code>
199      * <code>services.JetspeedSecurity.caseinsensitive.upper = true/false</code>
200      *
201      * If <code>caseinsensitive.username</code> is true,
202      * then conversion is enabled and the username will be converted before
203      * being sent to the Authentication provider.
204      *
205      * @param username The username to be converted depending on configuration.
206      * @return The converted username.
207      *
208      */

209     public String JavaDoc convertUserName(String JavaDoc username)
210     {
211         if (caseInsensitiveUsername)
212         {
213             username = (caseInsensitiveUpper) ? username.toUpperCase() : username.toLowerCase();
214         }
215         return username;
216     }
217
218     /*
219      * During logon, the password can be case sensitive or case insensitive.
220      *
221      * Given a password, converts the password to either lower or upper case.
222      * This optional feature is configurable from the JetspeedSecurity.properties:
223      *
224      * <code>services.JetspeedSecurity.caseinsensitive.password = true/false</code>
225      * <code>services.JetspeedSecurity.caseinsensitive.upper = true/false</code>
226      *
227      * If <code>caseinsensitive.password</code> is true,
228      * then conversion is enabled and the password will be converted before
229      * being sent to the Authentication provider.
230      *
231      * @param password The password to be converted depending on configuration.
232      * @return The converted password.
233      *
234      */

235     public String JavaDoc convertPassword(String JavaDoc password)
236     {
237         if (caseInsensitivePassword)
238         {
239             password = (caseInsensitiveUpper) ? password.toUpperCase() : password.toLowerCase();
240         }
241         return password;
242     }
243
244     /*
245      * Logon Failure / Account Disabling Feature
246      *
247      * Checks and tracks failed user-logon attempts.
248      * If the user fails to logon after a configurable number of logon attempts,
249      * then the user's account will be disabled.
250      *
251      * This optional feature is configurable from the JetspeedSecurity.properties:
252      *
253      * <code>services.JetspeedSecurity.logon.auto.disable=false</code>
254      *
255      * The example setting below allows for 3 logon strikes per 300 seconds.
256      * When the strike.count is exceeded over the strike.interval, the account
257      * is disabled. The strike.max is the cumulative maximum.
258      *
259      * <code>services.JetspeedSecurity.logon.strike.count=3</code>
260      * <code>services.JetspeedSecurity.logon.strike.interval=300</code>
261      * <code>services.JetspeedSecurity.logon.strike.max=10</code>
262      *
263      * These settings are not persisted, and in a distributed environment are
264      * only tracked per node.
265      *
266      * @param username The username to be checked.
267      * @return True if the strike count reached the maximum threshold and the
268      * user's account was disabled, otherwise False.
269      *
270      */

271     public boolean checkDisableAccount(String JavaDoc username)
272     {
273         username = convertUserName(username);
274  
275         // TODO: make this work across a cluster of servers
276
UserLogonStats stat = (UserLogonStats)users.get(username);
277         if (stat == null)
278         {
279             stat = new UserLogonStats(username);
280             synchronized (sem)
281             {
282                 users.put(username, stat);
283             }
284         }
285         boolean disabled = stat.failCheck(strikeCount, strikeInterval, strikeMax);
286
287         if (disabled)
288         {
289             try
290             {
291                 // disable the account
292
JetspeedUser user = (JetspeedUser)JetspeedSecurity.getUser(username);
293                 if (user != null)
294                 {
295                     user.setDisabled(true);
296                     JetspeedSecurity.saveUser(user);
297                 }
298             }
299             catch (Exception JavaDoc e)
300             {
301                  logger.error("Could not disable user: " + username, e);
302             }
303         }
304         return disabled;
305     }
306
307     /*
308      * Logon Failure / Account Disabling Feature
309      *
310      * Returns state of the the logon failure / account disabling feature.
311      *
312      * If the user fails to logon after a configurable number of logon attempts,
313      * then the user's account will be disabled.
314      *
315      * @see JetspeedSecurityService#checkLogonFailures
316      *
317      * @return True if the feature is enabled, false if the feature is disabled.
318      *
319      */

320     public boolean isDisableAccountCheckEnabled()
321     {
322         return autoLogonDisable;
323     }
324
325     
326     /*
327      * Logon Failure / Account Disabling Feature
328      *
329      * Resets counters for the logon failure / account disabling feature.
330      *
331      * If the user fails to logon after a configurable number of logon attempts,
332      * then the user's account will be disabled.
333      *
334      * @see JetspeedSecurityService#checkLogonFailures
335      *
336      * @param username The username to reset the logon failure counters.
337      *
338      */

339     public void resetDisableAccountCheck(String JavaDoc username)
340     {
341         // TODO: make this work across a cluster of servers
342
username = convertUserName(username);
343         UserLogonStats stat = (UserLogonStats)users.get(username);
344         if (stat == null)
345         {
346             stat = new UserLogonStats(username);
347             synchronized (sem)
348             {
349                 users.put(username, stat);
350             }
351         }
352         stat.reset();
353     }
354     
355
356     //////////////////////////////////////////////////////////////////////////
357
//
358
// Optional JetspeedSecurity Helpers
359
//
360
//////////////////////////////////////////////////////////////////////////
361

362     /**
363      * Helper to UserManagement.
364      * Retrieves a <code>JetspeedUser</code> given the primary principle username.
365      * The principal can be any valid Jetspeed Security Principal:
366      * <code>org.apache.jetspeed.om.security.UserNamePrincipal</code>
367      * <code>org.apache.jetspeed.om.security.UserIdPrincipal</code>
368      *
369      * The security service may optionally check the current user context
370      * to determine if the requestor has permission to perform this action.
371      *
372      * @param username The username principal.
373      * @return a <code>JetspeedUser</code> associated to the principal identity.
374      * @exception UserException when the security provider has a general failure retrieving a user.
375      * @exception UnknownUserException when the security provider cannot match
376      * the principal identity to a user.
377      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
378      */

379
380     public JetspeedUser getUser(String JavaDoc username)
381         throws JetspeedSecurityException
382     {
383         return JetspeedUserManagement.getUser(new UserNamePrincipal(username));
384     }
385
386
387     /**
388      * Helper to PortalAuthorization.
389      * Gets a <code>JetspeedUser</code> from rundata, authorize user to perform the secured action on
390      * the given <code>Portlet</code> resource. If the user does not have
391      * sufficient privilege to perform the action on the resource, the check returns false,
392      * otherwise when sufficient privilege is present, checkPermission returns true.
393      *
394      * @param rundata request that the user is taken from rundatas
395      * @param action the secured action to be performed on the resource by the user.
396      * @param portlet the portlet resource.
397      * @return boolean true if the user has sufficient privilege.
398      */

399     public boolean checkPermission(JetspeedRunData runData, String JavaDoc action, Portlet portlet)
400     {
401         return JetspeedPortalAccessController.checkPermission(runData.getJetspeedUser(),
402                                                        portlet,
403                                                        action);
404     }
405
406     /**
407      * Helper to PortalAuthorization.
408      * Gets a <code>JetspeedUser</code> from rundata, authorize user to perform the secured action on
409      * the given <code>Entry</code> resource. If the user does not have
410      * sufficient privilege to perform the action on the resource, the check returns false,
411      * otherwise when sufficient privilege is present, checkPermission returns true.
412      *
413      * @param rundata request that the user is taken from rundatas
414      * @param action the secured action to be performed on the resource by the user.
415      * @param entry the portal entry resource.
416      * @return boolean true if the user has sufficient privilege.
417     public boolean checkPermission(JetspeedRunData runData, String action, RegistryEntry entry)
418     {
419         return JetspeedPortalAccessController.checkPermission(runData.getJetspeedUser(),
420                                                        entry,
421                                                        action);
422     }
423      */

424
425     /*
426      * Security configuration setting to disable all action buttons for the Anon user
427      * This setting is readonly and is edited in the JetspeedSecurity deployment
428      *
429      *
430      * @return True if the feature actions are disabled for the anon user
431      *
432      */

433     public boolean areActionsDisabledForAnon()
434     {
435         return actionsAnonDisable;
436     }
437
438     /*
439      * Security configuration setting to disable all action buttons for all users
440      * This setting is readonly and is edited in the JetspeedSecurity deployment
441      *
442      *
443      * @return True if the feature actions are disabled for the all users
444      *
445      */

446     public boolean areActionsDisabledForAllUsers()
447     {
448         return actionsAllUsersDisable;
449     }
450
451    /*
452      * Gets the name of the anonymous user account if applicable
453      *
454      *
455      * @return String the name of the anonymous user account
456      *
457      */

458     public String JavaDoc getAnonymousUserName()
459     {
460         return anonymousUser;
461     }
462
463     /*
464      * Gets the list of administrative roles
465      *
466      * @return list of admin roles
467      */

468      public List JavaDoc getAdminRoles()
469      {
470         List JavaDoc result = new ArrayList JavaDoc();
471         for (int i = 0; i < adminRoles.length; i++)
472         {
473             result.add(adminRoles[i]);
474         }
475         
476         return result;
477      }
478
479     /**
480      * Returns true if user has administrative role
481      *
482      * @param user
483      * @return true if user has administrative role
484      */

485     public boolean hasAdminRole(User user)
486     {
487         String JavaDoc username = user.getUserName();
488         try
489         {
490             List JavaDoc adminRoles = getAdminRoles();
491             for (Iterator JavaDoc it = adminRoles.iterator(); it.hasNext();)
492             {
493                 if (JetspeedSecurity.hasRole(username, (String JavaDoc)it.next()))
494                 {
495                     return true;
496                 }
497             }
498         }
499         catch (Exception JavaDoc e)
500         {
501             logger.error(e);
502         }
503         
504         return false;
505     }
506
507 }
508
509
Popular Tags