Merged V3.2 to HEAD

Auto-reformat added 20 minutes of work!
   17456: Fix for: ETHREEOH-1465: It's impossible to get the login history for a given user (Audit)
   17463: Fixed ETHREEOH-3363: CLONE -Regression: readOnly settings causing bootstrap to fail


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18144 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-01-19 14:40:38 +00:00
parent c67a5c18d2
commit c8dc9b9bc2
10 changed files with 177 additions and 19 deletions

View File

@@ -135,13 +135,16 @@
<Method name="setAuthentication" mode="all"/> <Method name="setAuthentication" mode="all"/>
<Method name="deleteAuthentication" mode="all"/> <Method name="deleteAuthentication" mode="all"/>
<Method name="setAuthenticationEnabled" mode="all"/> <Method name="setAuthenticationEnabled" mode="all"/>
<Method name="authenticate" mode="all"/> <Method name="authenticate" mode="all" auditInternal="true"/>
<Method name="authenticateAsGuest" mode="all"/> <Method name="authenticateAsGuest" mode="all"/>
<Method name="authenticationExists" mode="all"/> <Method name="authenticationExists" mode="all"/>
<Method name="invalidateUserSession" mode="all"/> <Method name="invalidateUserSession" mode="all"/>
<Method name="invalidateTicket" mode="all"/> <Method name="invalidateTicket" mode="all"/>
<Method name="validate" mode="all"/> <Method name="validate" mode="all"/>
<Method name="clearCurrentSecurityContext" mode="all"/> <Method name="clearCurrentSecurityContext" mode="all"/>
<!-- audit the creation of new tickets to follow SSO -->
<Method name="getNewTicket" mode="all" />
<Method name="getCurrentTicket" mode="none" auditInternal="true"/>
</Service> </Service>
<Service name="AuthorityService" mode="none"> <Service name="AuthorityService" mode="none">

View File

@@ -117,6 +117,9 @@
<property name="sysAdminParams"> <property name="sysAdminParams">
<ref bean="sysAdminParams" /> <ref bean="sysAdminParams" />
</property> </property>
<property name="auditComponent">
<ref bean="auditComponent" />
</property>
</bean> </bean>
<!-- CIFS authentication --> <!-- CIFS authentication -->

View File

@@ -80,6 +80,9 @@
<property name="sysAdminParams"> <property name="sysAdminParams">
<ref bean="sysAdminParams" /> <ref bean="sysAdminParams" />
</property> </property>
<property name="auditComponent">
<ref bean="auditComponent" />
</property>
</bean> </bean>
<!-- <!--

View File

@@ -48,6 +48,9 @@
<property name="sysAdminParams"> <property name="sysAdminParams">
<ref bean="sysAdminParams" /> <ref bean="sysAdminParams" />
</property> </property>
<property name="auditComponent">
<ref bean="auditComponent" />
</property>
</bean> </bean>
</beans> </beans>

View File

@@ -57,6 +57,9 @@
<property name="sysAdminParams"> <property name="sysAdminParams">
<ref bean="sysAdminParams" /> <ref bean="sysAdminParams" />
</property> </property>
<property name="auditComponent">
<ref bean="auditComponent" />
</property>
</bean> </bean>
<!-- CIFS authentication --> <!-- CIFS authentication -->

View File

@@ -95,6 +95,9 @@
<property name="sysAdminParams"> <property name="sysAdminParams">
<ref bean="sysAdminParams" /> <ref bean="sysAdminParams" />
</property> </property>
<property name="auditComponent">
<ref bean="auditComponent" />
</property>
</bean> </bean>
<!-- CIFS authentication and SMB session listener --> <!-- CIFS authentication and SMB session listener -->

View File

@@ -57,6 +57,12 @@ public class AuditBootstrap extends AbstractLifecycleBean
@Override @Override
protected void onBootstrap(ApplicationEvent event) protected void onBootstrap(ApplicationEvent event)
{ {
// Don't bootstrap if the system is read-only
if (transactionService.isReadOnly())
{
return;
}
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
{ {
public Void execute() throws Throwable public Void execute() throws Throwable

View File

@@ -70,6 +70,14 @@ public interface AuditComponent
* @since 2.1 * @since 2.1
*/ */
public void audit(String source, String description, NodeRef key, Object... args); public void audit(String source, String description, NodeRef key, Object... args);
/**
* Add an audit entry - without invoking the method invocation.
* Only the method arguments can be audited.
*
* @since 3.2
*/
void beforeMethodCallManualAudit(Class<?> clazz, Object target, String method, Object ... args);
/** /**
* Get the audit trail for a node. * Get the audit trail for a node.

View File

@@ -64,11 +64,12 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.util.PathMapper; import org.alfresco.util.PathMapper;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.extensions.surf.util.ParameterCheck;
/** /**
* The default audit component implementation. TODO: Implement before, after and exception filtering. At the moment * The default audit component implementation. TODO: Implement before, after and exception filtering. At the moment
@@ -234,7 +235,7 @@ public class AuditComponentImpl implements AuditComponent
{ {
logger.debug("Auditing - " + serviceName + "." + methodName); logger.debug("Auditing - " + serviceName + "." + methodName);
} }
return auditImpl(mi); return auditImpl(mi, true);
} }
else else
{ {
@@ -242,7 +243,7 @@ public class AuditComponentImpl implements AuditComponent
{ {
logger.debug("UnknownService." + methodName); logger.debug("UnknownService." + methodName);
} }
return auditImpl(mi); return auditImpl(mi, true);
} }
} }
@@ -298,16 +299,20 @@ public class AuditComponentImpl implements AuditComponent
* @throws Throwable - * @throws Throwable -
* any Throwable that can be thrown by th audtied method. * any Throwable that can be thrown by th audtied method.
*/ */
public Object auditImpl(MethodInvocation mi) throws Throwable public Object auditImpl(MethodInvocation mi, boolean execute) throws Throwable
{ {
final AuditState auditInfo = new AuditState(auditConfiguration); final AuditState auditInfo = new AuditState(auditConfiguration);
// RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi); // RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi);
AuditMode auditMode = AuditMode.UNSET; AuditMode auditMode = AuditMode.UNSET;
try try
{ {
Object o = null;
auditMode = beforeInvocation(auditMode, auditInfo, mi); auditMode = beforeInvocation(auditMode, auditInfo, mi);
Object o = mi.proceed(); if (execute)
auditMode = postInvocation(auditMode, auditInfo, mi, o); {
o = mi.proceed();
auditMode = postInvocation(auditMode, auditInfo, mi, o);
}
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS)) if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS))
{ {
RetryingTransactionCallback<Object> cb = new RetryingTransactionCallback<Object>() RetryingTransactionCallback<Object> cb = new RetryingTransactionCallback<Object>()
@@ -611,6 +616,120 @@ public class AuditComponentImpl implements AuditComponent
} }
} }
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.AuditComponent#beforeMethodCallManualAudit(org.aopalliance.intercept.MethodInvocation)
*/
@SuppressWarnings("unchecked")
public void beforeMethodCallManualAudit(Class clazz, Object target, String methodName, Object ... args)
{
Class[] argTypes = new Class[args.length];
for(int i = 0; i < args.length; i++)
{
argTypes[i] = args[i].getClass();
}
Method method;
try
{
method = clazz.getMethod(methodName, argTypes);
}
catch (SecurityException e1)
{
return;
}
catch (NoSuchMethodException e1)
{
return;
}
MethodInvocation methodInvocation = new ReflectiveMethodInvocation(null, target, method, args, null, null) {};
if ((auditFlag.get() == null) || (!auditFlag.get().booleanValue()))
{
if (auditModel instanceof AuditEntry && ((AuditEntry) auditModel).getEnabled() == TrueFalseUnset.TRUE)
{
boolean auditInternal = (auditModel.getAuditInternalServiceMethods(methodInvocation) == TrueFalseUnset.TRUE);
try
{
String serviceName = publicServiceIdentifier.getPublicServiceName(methodInvocation);
if (!auditInternal)
{
auditFlag.set(Boolean.TRUE);
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Auditing internal service use for - " + serviceName + "." + methodName);
}
}
if (method.isAnnotationPresent(Auditable.class))
{
if (serviceName != null)
{
if (logger.isDebugEnabled())
{
logger.debug("Auditing - " + serviceName + "." + methodName);
}
try
{
auditImpl(methodInvocation, false);
}
catch (Throwable e)
{
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("UnknownService." + methodName);
}
try
{
auditImpl(methodInvocation, false);
}
catch (Throwable e)
{
}
}
}
else if (method.isAnnotationPresent(NotAuditable.class))
{
if (logger.isDebugEnabled())
{
logger.debug("Not Audited. " + serviceName + "." + methodName);
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Unannotated service method " + serviceName + "." + methodName);
}
if (method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAnnotationPresent(PublicService.class))
{
throw new RuntimeException("Unannotated service method " + serviceName + "." + methodName);
}
}
}
finally
{
if (!auditInternal)
{
auditFlag.set(Boolean.FALSE);
}
}
}
}
}
/** /**
* A simple audit entry Currently we ignore filtering here. * A simple audit entry Currently we ignore filtering here.
*/ */

View File

@@ -24,11 +24,16 @@
*/ */
package org.alfresco.repo.security.authentication; package org.alfresco.repo.security.authentication;
import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import org.alfresco.repo.audit.AuditComponent;
import org.alfresco.repo.management.subsystems.ActivateableBean; import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.security.authentication.AuthenticationComponent.UserNameValidationMode; import org.alfresco.repo.security.authentication.AuthenticationComponent.UserNameValidationMode;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
public class AuthenticationServiceImpl extends AbstractAuthenticationService implements ActivateableBean public class AuthenticationServiceImpl extends AbstractAuthenticationService implements ActivateableBean
{ {
@@ -36,6 +41,8 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService imp
TicketComponent ticketComponent; TicketComponent ticketComponent;
AuditComponent auditComponent;
private String domain; private String domain;
private boolean allowsUserCreation = true; private boolean allowsUserCreation = true;
@@ -58,7 +65,16 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService imp
{ {
this.authenticationComponent = authenticationComponent; this.authenticationComponent = authenticationComponent;
} }
/**
* @param auditComponent the auditComponent to set
*/
public void setAuditComponent(AuditComponent auditComponent)
{
this.auditComponent = auditComponent;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive() * @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
@@ -85,8 +101,7 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService imp
throw ae; throw ae;
} }
ticketComponent.clearCurrentTicket(); ticketComponent.clearCurrentTicket();
getCurrentTicket(null);
ticketComponent.getCurrentTicket(userName, null, true); // to ensure new ticket is created (even if client does not explicitly call getCurrentTicket)
} }
public String getCurrentUserName() throws AuthenticationException public String getCurrentUserName() throws AuthenticationException
@@ -146,24 +161,16 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService imp
String ticket = ticketComponent.getCurrentTicket(userName, sessionId, false); String ticket = ticketComponent.getCurrentTicket(userName, sessionId, false);
if (ticket == null) if (ticket == null)
{ {
try
{
preAuthenticationCheck(userName);
}
catch (AuthenticationException e)
{
clearCurrentSecurityContext();
throw e;
}
// If we get through the authentication check then it's safe to issue a new ticket (e.g. for // If we get through the authentication check then it's safe to issue a new ticket (e.g. for
// SSO/external-based login) // SSO/external-based login)
return ticketComponent.getCurrentTicket(userName, sessionId, true); return getNewTicket(sessionId);
} }
return ticket; return ticket;
} }
public String getNewTicket(String sessionId) public String getNewTicket(String sessionId)
{ {
auditComponent.beforeMethodCallManualAudit(AuthenticationService.class, this, "getNewTicket", "");
String userName = getCurrentUserName(); String userName = getCurrentUserName();
try try
{ {