/tags/release/7010/aipo/jetspeed/src/main/java/org/apache/jetspeed/services/security/JetspeedDBSecurityService.java
http://aipo.googlecode.com/ · Java · 508 lines · 220 code · 52 blank · 236 comment · 21 complexity · 71fdef2827bce9e0dfabfabd78738b34 MD5 · raw file
- /*
- * Copyright 2000-2001,2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.jetspeed.services.security;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import javax.servlet.ServletConfig;
- import org.apache.jetspeed.om.security.JetspeedUser;
- import org.apache.jetspeed.om.security.JetspeedUserFactory;
- import org.apache.jetspeed.om.security.UserNamePrincipal;
- import org.apache.jetspeed.portal.Portlet;
- import org.apache.jetspeed.services.JetspeedPortalAccessController;
- import org.apache.jetspeed.services.JetspeedSecurity;
- import org.apache.jetspeed.services.JetspeedUserManagement;
- import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
- import org.apache.jetspeed.services.logging.JetspeedLogger;
- import org.apache.jetspeed.services.rundata.JetspeedRunData;
- import org.apache.turbine.om.security.User;
- import org.apache.turbine.services.InitializationException;
- import org.apache.turbine.services.TurbineBaseService;
- import org.apache.turbine.services.TurbineServices;
- import org.apache.turbine.services.resources.ResourceService;
- /**
- * <p>This is an implementation of the <code>JetspeedSecurityService</code> interface.
- *
- *
- * @author <a href="mailto:david@bluesunrise.com">David Sean Taylor</a>
- * @author <a href="mailto:sgala@hisitech.com">Santiago Gala</a>
- * @version $Id: JetspeedDBSecurityService.java,v 1.25 2004/03/31 04:49:10 morciuch Exp $
- */
- public class JetspeedDBSecurityService extends TurbineBaseService
- implements JetspeedSecurityService
- {
- /**
- * Static initialization of the logger for this class
- */
- private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedDBSecurityService.class.getName());
-
- private final static String CONFIG_CASEINSENSITIVE_USERNAME = "caseinsensitive.username";
- private final static String CONFIG_CASEINSENSITIVE_PASSWORD = "caseinsensitive.password";
- private final static String CONFIG_CASEINSENSITIVE_UPPER = "caseinsensitive.upper";
- private final static String CONFIG_LOGON_STRIKE_COUNT = "logon.strike.count";
- private final static String CONFIG_LOGON_STRIKE_MAX = "logon.strike.max";
- private final static String CONFIG_LOGON_STRIKE_INTERVAL = "logon.strike.interval";
- private final static String CONFIG_LOGON_AUTO_DISABLE = "logon.auto.disable";
- private final static String CONFIG_ACTIONS_ANON_DISABLE = "actions.anon.disable";
- private final static String CONFIG_ACTIONS_ALLUSERS_DISABLE = "actions.allusers.disable";
- private final static String CONFIG_ACTIONS_ADMIN_ROLES = "admin.roles";
- private final static String CONFIG_NEWUSER_ROLES = "newuser.roles";
- private final static String CONFIG_DEFAULT_PERMISSION_LOGGEDIN = "permission.default.loggedin";
- private final static String CONFIG_DEFAULT_PERMISSION_ANONYMOUS = "permission.default.anonymous";
- private final static String CONFIG_ANONYMOUS_USER = "user.anonymous";
- private final static String [] DEFAULT_PERMISSIONS = {""};
- private final static String [] DEFAULT_CONFIG_NEWUSER_ROLES =
- { "user" };
- private final static String [] DEFAULT_ADMIN_ROLES =
- { "admin" };
- String roles[] = null;
- boolean caseInsensitiveUsername = false;
- boolean caseInsensitivePassword = false;
- boolean caseInsensitiveUpper = true;
- boolean actionsAnonDisable = true;
- boolean actionsAllUsersDisable = false;
- String anonymousUser = "anon";
- String[] adminRoles = null;
- int strikeCount = 3; // 3 within the interval
- int strikeMax = 20; // 20 total failures
- long strikeInterval = 300; // five minutes
- boolean autoLogonDisable = false;
- private static HashMap users = new HashMap();
- private static Object sem = new Object();
- /**
- * This is the early initialization method called by the
- * Turbine <code>Service</code> framework
- * @param conf The <code>ServletConfig</code>
- * @exception throws a <code>InitializationException</code> if the service
- * fails to initialize
- */
- public synchronized void init(ServletConfig conf) throws InitializationException
- {
- // already initialized
- if (getInit()) return;
- super.init(conf);
- // get configuration parameters from Jetspeed Resources
- ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
- .getResources(JetspeedSecurityService.SERVICE_NAME);
-
- try
- {
- roles = serviceConf.getStringArray(CONFIG_NEWUSER_ROLES);
- adminRoles = serviceConf.getStringArray(CONFIG_ACTIONS_ADMIN_ROLES);
- }
- catch (Exception e)
- {}
-
- if (null == roles || roles.length == 0)
- {
- roles = DEFAULT_CONFIG_NEWUSER_ROLES;
- }
- if (null == adminRoles || adminRoles.length == 0)
- {
- adminRoles = DEFAULT_ADMIN_ROLES;
- }
- caseInsensitiveUsername = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_USERNAME, caseInsensitiveUsername);
- caseInsensitivePassword = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_PASSWORD, caseInsensitivePassword);
- caseInsensitiveUpper = serviceConf.getBoolean(CONFIG_CASEINSENSITIVE_UPPER, caseInsensitiveUpper);
- strikeCount = serviceConf.getInt(CONFIG_LOGON_STRIKE_COUNT, strikeCount);
- strikeInterval = serviceConf.getLong(CONFIG_LOGON_STRIKE_INTERVAL, strikeInterval);
- strikeMax = serviceConf.getInt(CONFIG_LOGON_STRIKE_MAX, strikeMax);
- autoLogonDisable = serviceConf.getBoolean(CONFIG_LOGON_AUTO_DISABLE, autoLogonDisable);
- actionsAnonDisable = serviceConf.getBoolean(CONFIG_ACTIONS_ANON_DISABLE, actionsAnonDisable);
- actionsAllUsersDisable = serviceConf.getBoolean(CONFIG_ACTIONS_ALLUSERS_DISABLE, actionsAllUsersDisable);
- anonymousUser = serviceConf.getString(CONFIG_ANONYMOUS_USER, anonymousUser);
- // initialization done
- setInit(true);
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // Required JetspeedSecurity Functions
- //
- // Required Features provided by default JetspeedSecurity
- //
- //////////////////////////////////////////////////////////////////////////
- /*
- * Factory to create a new JetspeedUser, using JetspeedUserFactory.
- * The class that is created by the default JetspeedUserFactory is configured
- * in the JetspeedSecurity properties:
- *
- * services.JetspeedSecurity.user.class=
- * org.apache.jetspeed.om.security.BaseJetspeedUser
- *
- * @return JetspeedUser a newly created user that implements JetspeedUser.
- */
- public JetspeedUser getUserInstance()
- {
- try
- {
- return JetspeedUserFactory.getInstance();
- }
- catch (UserException e)
- {
- return null;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // Optional JetspeedSecurity Features
- //
- // Features are not required to be implemented by Security Provider
- //
- //////////////////////////////////////////////////////////////////////////
- /*
- * During logon, the username can be case sensitive or case insensitive.
- *
- * Given a username, converts the username to either lower or upper case.
- * This optional feature is configurable from the JetspeedSecurity.properties:
- *
- * <code>services.JetspeedSecurity.caseinsensitive.username = true/false</code>
- * <code>services.JetspeedSecurity.caseinsensitive.upper = true/false</code>
- *
- * If <code>caseinsensitive.username</code> is true,
- * then conversion is enabled and the username will be converted before
- * being sent to the Authentication provider.
- *
- * @param username The username to be converted depending on configuration.
- * @return The converted username.
- *
- */
- public String convertUserName(String username)
- {
- if (caseInsensitiveUsername)
- {
- username = (caseInsensitiveUpper) ? username.toUpperCase() : username.toLowerCase();
- }
- return username;
- }
- /*
- * During logon, the password can be case sensitive or case insensitive.
- *
- * Given a password, converts the password to either lower or upper case.
- * This optional feature is configurable from the JetspeedSecurity.properties:
- *
- * <code>services.JetspeedSecurity.caseinsensitive.password = true/false</code>
- * <code>services.JetspeedSecurity.caseinsensitive.upper = true/false</code>
- *
- * If <code>caseinsensitive.password</code> is true,
- * then conversion is enabled and the password will be converted before
- * being sent to the Authentication provider.
- *
- * @param password The password to be converted depending on configuration.
- * @return The converted password.
- *
- */
- public String convertPassword(String password)
- {
- if (caseInsensitivePassword)
- {
- password = (caseInsensitiveUpper) ? password.toUpperCase() : password.toLowerCase();
- }
- return password;
- }
- /*
- * Logon Failure / Account Disabling Feature
- *
- * Checks and tracks failed user-logon attempts.
- * If the user fails to logon after a configurable number of logon attempts,
- * then the user's account will be disabled.
- *
- * This optional feature is configurable from the JetspeedSecurity.properties:
- *
- * <code>services.JetspeedSecurity.logon.auto.disable=false</code>
- *
- * The example setting below allows for 3 logon strikes per 300 seconds.
- * When the strike.count is exceeded over the strike.interval, the account
- * is disabled. The strike.max is the cumulative maximum.
- *
- * <code>services.JetspeedSecurity.logon.strike.count=3</code>
- * <code>services.JetspeedSecurity.logon.strike.interval=300</code>
- * <code>services.JetspeedSecurity.logon.strike.max=10</code>
- *
- * These settings are not persisted, and in a distributed environment are
- * only tracked per node.
- *
- * @param username The username to be checked.
- * @return True if the strike count reached the maximum threshold and the
- * user's account was disabled, otherwise False.
- *
- */
- public boolean checkDisableAccount(String username)
- {
- username = convertUserName(username);
-
- // TODO: make this work across a cluster of servers
- UserLogonStats stat = (UserLogonStats)users.get(username);
- if (stat == null)
- {
- stat = new UserLogonStats(username);
- synchronized (sem)
- {
- users.put(username, stat);
- }
- }
- boolean disabled = stat.failCheck(strikeCount, strikeInterval, strikeMax);
- if (disabled)
- {
- try
- {
- // disable the account
- JetspeedUser user = (JetspeedUser)JetspeedSecurity.getUser(username);
- if (user != null)
- {
- user.setDisabled("T");
- JetspeedSecurity.saveUser(user);
- }
- }
- catch (Exception e)
- {
- logger.error("Could not disable user: " + username, e);
- }
- }
- return disabled;
- }
- /*
- * Logon Failure / Account Disabling Feature
- *
- * Returns state of the the logon failure / account disabling feature.
- *
- * If the user fails to logon after a configurable number of logon attempts,
- * then the user's account will be disabled.
- *
- * @see JetspeedSecurityService#checkLogonFailures
- *
- * @return True if the feature is enabled, false if the feature is disabled.
- *
- */
- public boolean isDisableAccountCheckEnabled()
- {
- return autoLogonDisable;
- }
-
- /*
- * Logon Failure / Account Disabling Feature
- *
- * Resets counters for the logon failure / account disabling feature.
- *
- * If the user fails to logon after a configurable number of logon attempts,
- * then the user's account will be disabled.
- *
- * @see JetspeedSecurityService#checkLogonFailures
- *
- * @param username The username to reset the logon failure counters.
- *
- */
- public void resetDisableAccountCheck(String username)
- {
- // TODO: make this work across a cluster of servers
- username = convertUserName(username);
- UserLogonStats stat = (UserLogonStats)users.get(username);
- if (stat == null)
- {
- stat = new UserLogonStats(username);
- synchronized (sem)
- {
- users.put(username, stat);
- }
- }
- stat.reset();
- }
-
- //////////////////////////////////////////////////////////////////////////
- //
- // Optional JetspeedSecurity Helpers
- //
- //////////////////////////////////////////////////////////////////////////
- /**
- * Helper to UserManagement.
- * Retrieves a <code>JetspeedUser</code> given the primary principle username.
- * The principal can be any valid Jetspeed Security Principal:
- * <code>org.apache.jetspeed.om.security.UserNamePrincipal</code>
- * <code>org.apache.jetspeed.om.security.UserIdPrincipal</code>
- *
- * The security service may optionally check the current user context
- * to determine if the requestor has permission to perform this action.
- *
- * @param username The username principal.
- * @return a <code>JetspeedUser</code> associated to the principal identity.
- * @exception UserException when the security provider has a general failure retrieving a user.
- * @exception UnknownUserException when the security provider cannot match
- * the principal identity to a user.
- * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
- */
- public JetspeedUser getUser(String username)
- throws JetspeedSecurityException
- {
- return JetspeedUserManagement.getUser(new UserNamePrincipal(username));
- }
- /**
- * Helper to PortalAuthorization.
- * Gets a <code>JetspeedUser</code> from rundata, authorize user to perform the secured action on
- * the given <code>Portlet</code> resource. If the user does not have
- * sufficient privilege to perform the action on the resource, the check returns false,
- * otherwise when sufficient privilege is present, checkPermission returns true.
- *
- * @param rundata request that the user is taken from rundatas
- * @param action the secured action to be performed on the resource by the user.
- * @param portlet the portlet resource.
- * @return boolean true if the user has sufficient privilege.
- */
- public boolean checkPermission(JetspeedRunData runData, String action, Portlet portlet)
- {
- return JetspeedPortalAccessController.checkPermission(runData.getJetspeedUser(),
- portlet,
- action);
- }
- /**
- * Helper to PortalAuthorization.
- * Gets a <code>JetspeedUser</code> from rundata, authorize user to perform the secured action on
- * the given <code>Entry</code> resource. If the user does not have
- * sufficient privilege to perform the action on the resource, the check returns false,
- * otherwise when sufficient privilege is present, checkPermission returns true.
- *
- * @param rundata request that the user is taken from rundatas
- * @param action the secured action to be performed on the resource by the user.
- * @param entry the portal entry resource.
- * @return boolean true if the user has sufficient privilege.
- public boolean checkPermission(JetspeedRunData runData, String action, RegistryEntry entry)
- {
- return JetspeedPortalAccessController.checkPermission(runData.getJetspeedUser(),
- entry,
- action);
- }
- */
- /*
- * Security configuration setting to disable all action buttons for the Anon user
- * This setting is readonly and is edited in the JetspeedSecurity deployment
- *
- *
- * @return True if the feature actions are disabled for the anon user
- *
- */
- public boolean areActionsDisabledForAnon()
- {
- return actionsAnonDisable;
- }
- /*
- * Security configuration setting to disable all action buttons for all users
- * This setting is readonly and is edited in the JetspeedSecurity deployment
- *
- *
- * @return True if the feature actions are disabled for the all users
- *
- */
- public boolean areActionsDisabledForAllUsers()
- {
- return actionsAllUsersDisable;
- }
- /*
- * Gets the name of the anonymous user account if applicable
- *
- *
- * @return String the name of the anonymous user account
- *
- */
- public String getAnonymousUserName()
- {
- return anonymousUser;
- }
- /*
- * Gets the list of administrative roles
- *
- * @return list of admin roles
- */
- public List getAdminRoles()
- {
- List result = new ArrayList();
- for (int i = 0; i < adminRoles.length; i++)
- {
- result.add(adminRoles[i]);
- }
-
- return result;
- }
- /**
- * Returns true if user has administrative role
- *
- * @param user
- * @return true if user has administrative role
- */
- public boolean hasAdminRole(User user)
- {
- String username = user.getUserName();
- try
- {
- List adminRoles = getAdminRoles();
- for (Iterator it = adminRoles.iterator(); it.hasNext();)
- {
- if (JetspeedSecurity.hasRole(username, (String)it.next()))
- {
- return true;
- }
- }
- }
- catch (Exception e)
- {
- logger.error(e);
- }
-
- return false;
- }
- }