mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-16 17:55:15 +00:00
Merged V2.2 to HEAD
7266: Updates to JMX-based admin 7270: Add JMX-managed attribute 'maxUsers' and related startup property (server.maxusers) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8243 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
17b806c6c0
commit
1f36c62b18
@ -135,6 +135,8 @@
|
||||
<bean id="RepoServerMgmt" class="org.alfresco.repo.admin.RepoServerMgmt">
|
||||
<property name="transactionService"><ref bean="transactionService"/></property>
|
||||
<property name="authenticationService"><ref bean="authenticationService"/></property>
|
||||
<property name="maxUsers"><value>${server.maxusers}</value></property>
|
||||
<property name="singleUserOnly"><value>${server.singleuseronly.name}</value></property>
|
||||
</bean>
|
||||
|
||||
|
||||
|
@ -44,6 +44,18 @@ index.tracking.maxRecordSetSize=1000
|
||||
# Change the failure behaviour of the configuration checker
|
||||
system.bootstrap.config_check.strict=true
|
||||
|
||||
# Server Single User Mode
|
||||
# note:
|
||||
# only allow named user (note: if blank or not set then will allow all users)
|
||||
# assuming maxusers is not set to 0
|
||||
#server.singleuseronly.name=admin
|
||||
|
||||
# Server Max Users - limit number of users with non-expired tickets
|
||||
# note:
|
||||
# -1 allows any number of users, assuming not in single-user mode
|
||||
# 0 prevents further logins, including the ability to enter single-user mode
|
||||
server.maxusers=-1
|
||||
|
||||
#
|
||||
# Properties to limit resources spent on individual searches
|
||||
#
|
||||
|
@ -27,7 +27,10 @@ package org.alfresco.repo.admin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationServiceImpl;
|
||||
import org.alfresco.repo.transaction.TransactionServiceImpl;
|
||||
import org.alfresco.service.license.LicenseService;
|
||||
@ -47,6 +50,8 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
private TransactionServiceImpl transactionService;
|
||||
private AuthenticationServiceImpl authenticationService;
|
||||
|
||||
// property key should be the same as the one in core-services-context.xml (to allow repo to start in multi-user mode even if the property is not set)
|
||||
private final static String PROPERTY_KEY_SINGLE_USER_ONLY = "${server.singleuseronly.name}";
|
||||
|
||||
public void setTransactionService(TransactionServiceImpl transactionService)
|
||||
{
|
||||
@ -71,13 +76,13 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
{
|
||||
if (readOnly && isReadOnly())
|
||||
{
|
||||
log.info("Alfresco Repository is already READONLY");
|
||||
log.info("Alfresco is already read-only");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readOnly && !isReadOnly())
|
||||
{
|
||||
log.info("Alfresco Repository is already WRITABLE");
|
||||
log.info("Alfresco is already read-write");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,11 +105,11 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
|
||||
if (readOnly)
|
||||
{
|
||||
log.info("Alfresco Repository set to READONLY");
|
||||
log.info("Alfresco set to be read-only");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Alfresco Repository set to WRITABLE");
|
||||
log.info("Alfresco set to be read-write");
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +123,7 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
}
|
||||
|
||||
// Note: implementing counts as managed attributes (without params) means that
|
||||
// certain JMX consoles can create graphs
|
||||
// certain JMX consoles can monitor
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@ -165,7 +170,8 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
public String[] listUserNamesNonExpired()
|
||||
{
|
||||
Set<String> userSet = authenticationService.getUsersWithTickets(true);
|
||||
return userSet.toArray(new String[0]);
|
||||
SortedSet<String> sorted = new TreeSet<String>(userSet);
|
||||
return sorted.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -175,7 +181,8 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
public String[] listUserNamesAll()
|
||||
{
|
||||
Set<String> userSet = authenticationService.getUsersWithTickets(false);
|
||||
return userSet.toArray(new String[0]);
|
||||
SortedSet<String> sorted = new TreeSet<String>(userSet);
|
||||
return sorted.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -184,7 +191,9 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
*/
|
||||
public int invalidateTicketsExpired()
|
||||
{
|
||||
return authenticationService.invalidateTickets(true);
|
||||
int count = authenticationService.invalidateTickets(true);
|
||||
log.info("Expired tickets invalidated: " + count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -193,24 +202,132 @@ public class RepoServerMgmt implements RepoServerMgmtMBean, ApplicationContextAw
|
||||
*/
|
||||
public int invalidateTicketsAll()
|
||||
{
|
||||
return authenticationService.invalidateTickets(false);
|
||||
int count = authenticationService.invalidateTickets(false);
|
||||
log.info("All tickets invalidated: " + count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.mbeans.RepoServerMgmtMBean#allowSingleUserOnly(java.lang.String)
|
||||
* @see org.alfresco.repo.admin.RepoServerMgmtMBean#invalidateUser(java.lang.String)
|
||||
*/
|
||||
public void allowSingleUserOnly(String allowedUsername)
|
||||
public void invalidateUser(String username)
|
||||
{
|
||||
authenticationService.invalidateUserSession(username);
|
||||
log.info("User invalidated: " + username);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.admin.RepoServerMgmtMBean#setSingleUserOnly(java.lang.String)
|
||||
*/
|
||||
public void setSingleUserOnly(String allowedUsername)
|
||||
{
|
||||
int maxUsers = getMaxUsers();
|
||||
|
||||
List<String> allowedUsers = null;
|
||||
if (allowedUsername != null)
|
||||
if ((allowedUsername != null) && (! allowedUsername.equals("")))
|
||||
{
|
||||
if (! allowedUsername.equals(PROPERTY_KEY_SINGLE_USER_ONLY))
|
||||
{
|
||||
allowedUsers = new ArrayList<String>(0);
|
||||
allowedUsers.add(allowedUsername);
|
||||
|
||||
invalidateTicketsAll();
|
||||
|
||||
if (maxUsers != 0)
|
||||
{
|
||||
log.info("Alfresco set to allow single-user (" + allowedUsername + ") logins");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Alfresco set to allow single-user (" + allowedUsername + ") logins - although further logins are currently prevented (limit = 0)");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maxUsers == -1)
|
||||
{
|
||||
log.info("Alfresco set to allow logins (no limit set)");
|
||||
}
|
||||
else if (maxUsers == 0)
|
||||
{
|
||||
log.info("Alfresco set to allow logins - although further logins are currently prevented (limit = 0)");
|
||||
}
|
||||
else if (maxUsers != 0)
|
||||
{
|
||||
log.info("Alfresco set to allow logins (limit = " + maxUsers + ")");
|
||||
}
|
||||
}
|
||||
|
||||
authenticationService.setAllowedUsers(allowedUsers);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.admin.RepoServerMgmtMBean#getSingleUserOnly()
|
||||
*/
|
||||
public String getSingleUserOnly()
|
||||
{
|
||||
List<String> allowedUsers = authenticationService.getAllowedUsers();
|
||||
if (allowedUsers != null)
|
||||
{
|
||||
if (allowedUsers.size() > 1)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected: more than one user allowed");
|
||||
}
|
||||
if (allowedUsers.size() == 1)
|
||||
{
|
||||
return allowedUsers.get(0);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.admin.RepoServerMgmtMBean#setMaxUsers(int)
|
||||
*/
|
||||
public void setMaxUsers(int maxUsers)
|
||||
{
|
||||
authenticationService.setMaxUsers(maxUsers);
|
||||
|
||||
String singleUserOnlyName = getSingleUserOnly();
|
||||
if (maxUsers == -1)
|
||||
{
|
||||
if ((singleUserOnlyName != null) && (! singleUserOnlyName.equals("")))
|
||||
{
|
||||
log.info("Alfresco set to allow logins (no limit set) - although currently restricted to single-user (" + singleUserOnlyName + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Alfresco set to allow logins (no limit set)");
|
||||
}
|
||||
}
|
||||
else if (maxUsers == 0)
|
||||
{
|
||||
log.info("Alfresco set to prevent further logins (limit = 0)");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((singleUserOnlyName != null) && (! singleUserOnlyName.equals("")))
|
||||
{
|
||||
log.info("Alfresco set to allow logins (limit = " + maxUsers + ") - although currently restricted to single-user (" + singleUserOnlyName + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Alfresco set to allow logins (limit = " + maxUsers + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.admin.RepoServerMgmtMBean#getMaxUsers()
|
||||
*/
|
||||
public int getMaxUsers()
|
||||
{
|
||||
return authenticationService.getMaxUsers();
|
||||
}
|
||||
}
|
||||
|
@ -24,14 +24,17 @@
|
||||
*/
|
||||
package org.alfresco.repo.admin;
|
||||
|
||||
|
||||
/**
|
||||
* Repository Server Management
|
||||
*
|
||||
* Note: The attributes/operations below can be clustered (ie. when configured all servers in the cluster will be affected)
|
||||
*
|
||||
*/
|
||||
public interface RepoServerMgmtMBean
|
||||
{
|
||||
/**
|
||||
* Set whether Repository allows writes or not
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @param readOnly true is READONLY, false is WRITEABLE
|
||||
*/
|
||||
public void setReadOnly(boolean readOnly);
|
||||
@ -39,8 +42,6 @@ public interface RepoServerMgmtMBean
|
||||
/**
|
||||
* Does the Repository allows writes or not ?
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return boolean true is READONLY, false is WRITEABLE
|
||||
*/
|
||||
public boolean isReadOnly();
|
||||
@ -50,8 +51,6 @@ public interface RepoServerMgmtMBean
|
||||
*
|
||||
* This may be higher than the user count, since a user can have more than one ticket/session
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return int number of non-expired tickets
|
||||
*/
|
||||
public int getTicketCountNonExpired();
|
||||
@ -61,8 +60,6 @@ public interface RepoServerMgmtMBean
|
||||
*
|
||||
* This may be higher than the user count, since a user can have more than one ticket/session
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return int number of tickets (non-expired and expired)
|
||||
*/
|
||||
public int getTicketCountAll();
|
||||
@ -72,8 +69,6 @@ public interface RepoServerMgmtMBean
|
||||
*
|
||||
* This may be lower than the ticket count, since a user can have more than one ticket/session
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return int number of non-expired users
|
||||
*/
|
||||
public int getUserCountNonExpired();
|
||||
@ -83,8 +78,6 @@ public interface RepoServerMgmtMBean
|
||||
*
|
||||
* This may be lower than the ticket count, since a user can have more than one ticket/session
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return int number of users (non-expired and expired)
|
||||
*/
|
||||
public int getUserCountAll();
|
||||
@ -92,8 +85,6 @@ public interface RepoServerMgmtMBean
|
||||
/**
|
||||
* Get set of unique non-expired usernames
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return String[] array of non-expired usernames
|
||||
*/
|
||||
public String[] listUserNamesNonExpired();
|
||||
@ -101,8 +92,6 @@ public interface RepoServerMgmtMBean
|
||||
/**
|
||||
* Get set of all unique usernames
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return String[] array of all usernames (non-expired and expired)
|
||||
*/
|
||||
public String[] listUserNamesAll();
|
||||
@ -110,8 +99,6 @@ public interface RepoServerMgmtMBean
|
||||
/**
|
||||
* Invalidate expired tickets
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
*
|
||||
* @return int count of expired invalidated tickets
|
||||
*/
|
||||
public int invalidateTicketsExpired();
|
||||
@ -125,15 +112,57 @@ public interface RepoServerMgmtMBean
|
||||
*/
|
||||
public int invalidateTicketsAll();
|
||||
|
||||
/**
|
||||
* Invalidate given users tickets
|
||||
*/
|
||||
public void invalidateUser(String username);
|
||||
|
||||
/**
|
||||
* Set whether Repository allows single user mode or not
|
||||
*
|
||||
* If single user mode is set then all tickets will be invalidated first before allowing the
|
||||
* named user to login (with one or more sessions)
|
||||
* named user to login (with one or more sessions) assuming maxUsers is not set to 0
|
||||
*
|
||||
* Note: This operation can be clustered (ie. all servers in the cluster will be affected)
|
||||
* Note: This can also be configured at startup. Refer to repository property (server.singleuseronly.name).
|
||||
*
|
||||
* @param String allowed username (eg. 'admin') or null to unset (ie. allow all users)
|
||||
*/
|
||||
public void allowSingleUserOnly(String allowedUsername);
|
||||
public void setSingleUserOnly(String allowedUsername);
|
||||
|
||||
/**
|
||||
* If Repository is in single user mode then return the name of the allowed user else return null
|
||||
*
|
||||
* @param String allowed username (eg. 'admin') or null (ie. allow all users)
|
||||
*/
|
||||
public String getSingleUserOnly();
|
||||
|
||||
/**
|
||||
* Set limit for max users and/or prevent further logins
|
||||
*
|
||||
* If number of non-expired logins is greater or equal to the limit then further logins will be prevented
|
||||
* otherwise valid login attempt will be permitted, unless the system is in single-user mode.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* Max users = 0 prevents further logins (will also prevent single-user mode login)
|
||||
* Max users = -1 allow logins (without a max limit)
|
||||
*
|
||||
* Note: This can also be configured at startup. Refer to repository property (server.maxusers).
|
||||
*
|
||||
* @param maxUsers
|
||||
*/
|
||||
public void setMaxUsers(int maxUsers);
|
||||
|
||||
/**
|
||||
* Get limit for max users
|
||||
*
|
||||
* If number of non-expired logins is greater or equal to the limit then further logins will be prevented
|
||||
* otherwise valid login attempt will be permitted. However, single-user mode will take precedence.
|
||||
*
|
||||
* Max users = 0 prevents further logins
|
||||
* Max users = -1 allow logins (without a max limit)
|
||||
*
|
||||
* @param int maxUsers
|
||||
*/
|
||||
public int getMaxUsers();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
|
||||
public class AuthenticationServiceImpl implements AuthenticationService
|
||||
{
|
||||
@ -49,7 +50,8 @@ public class AuthenticationServiceImpl implements AuthenticationService
|
||||
|
||||
// SysAdmin cache - used to cluster certain JMX operations
|
||||
private SimpleCache<String, Object> sysAdminCache;
|
||||
private final static String KEY_SYSADMIN_ALLOWED_USERS = "sysAdminCache.authAllowedUsers";
|
||||
private final static String KEY_SYSADMIN_ALLOWED_USERS = "sysAdminCache.authAllowedUsers"; // List<String>
|
||||
private final static String KEY_SYSADMIN_MAX_USERS = "sysAdminCache.authMaxUsers"; // Integer
|
||||
|
||||
|
||||
public AuthenticationServiceImpl()
|
||||
@ -130,6 +132,14 @@ public class AuthenticationServiceImpl implements AuthenticationService
|
||||
{
|
||||
throw new AuthenticationException("Username not allowed: " + userName);
|
||||
}
|
||||
|
||||
Integer maxUsers = (Integer)sysAdminCache.get(KEY_SYSADMIN_MAX_USERS);
|
||||
|
||||
if ((maxUsers != null) && (maxUsers != -1) && (ticketComponent.getUsersWithTickets(true).size() >= maxUsers))
|
||||
{
|
||||
throw new AuthenticationException("Max users exceeded: " + maxUsers);
|
||||
}
|
||||
|
||||
authenticationComponent.authenticate(userName, password);
|
||||
}
|
||||
catch(AuthenticationException ae)
|
||||
@ -167,6 +177,24 @@ public class AuthenticationServiceImpl implements AuthenticationService
|
||||
sysAdminCache.put(KEY_SYSADMIN_ALLOWED_USERS, allowedUsers);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> getAllowedUsers()
|
||||
{
|
||||
return (List<String>)sysAdminCache.get(KEY_SYSADMIN_ALLOWED_USERS);
|
||||
}
|
||||
|
||||
public void setMaxUsers(int maxUsers)
|
||||
{
|
||||
sysAdminCache.put(KEY_SYSADMIN_MAX_USERS, new Integer(maxUsers));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int getMaxUsers()
|
||||
{
|
||||
Integer maxUsers = (Integer)sysAdminCache.get(KEY_SYSADMIN_MAX_USERS);
|
||||
return (maxUsers == null ? -1 : maxUsers.intValue());
|
||||
}
|
||||
|
||||
public void invalidateTicket(String ticket) throws AuthenticationException
|
||||
{
|
||||
ticketComponent.invalidateTicketById(ticket);
|
||||
@ -219,8 +247,16 @@ public class AuthenticationServiceImpl implements AuthenticationService
|
||||
return authenticationComponent.isSystemUserName(getCurrentUserName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void authenticateAsGuest() throws AuthenticationException
|
||||
{
|
||||
List<String> allowedUsers = (List<String>)sysAdminCache.get(KEY_SYSADMIN_ALLOWED_USERS);
|
||||
|
||||
if ((allowedUsers != null) && (! allowedUsers.contains(PermissionService.GUEST_AUTHORITY)))
|
||||
{
|
||||
throw new AuthenticationException("Guest authentication is not allowed");
|
||||
}
|
||||
|
||||
authenticationComponent.setGuestUserAsCurrentUser();
|
||||
ticketComponent.clearCurrentTicket();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user