Moved to net.sf.acegisecurity.intercept.method.
This commit is contained in:
parent
738fd2161d
commit
3ece12c386
|
@ -1,158 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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 net.sf.acegisecurity;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.metadata.Attributes;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Stores a {@link ConfigAttributeDefinition} for each method signature defined
|
||||
* by Commons Attributes.
|
||||
*
|
||||
* <P>
|
||||
* This class will only detect those attributes which are defined for the:
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* The class-wide attributes defined for the intercepted class.
|
||||
* </li>
|
||||
* <li>
|
||||
* The class-wide attributes defined for interfaces explicitly implemented by
|
||||
* the intercepted class.
|
||||
* </li>
|
||||
* <li>
|
||||
* The method-specific attributes defined for the intercepted method of the
|
||||
* intercepted class.
|
||||
* </li>
|
||||
* <li>
|
||||
* The method-specific attributes defined by any explicitly implemented
|
||||
* interface if that interface contains a method signature matching that of
|
||||
* the intercepted method.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* Note that attributes defined against parent classes (either for their
|
||||
* methods or interfaces) are not detected. The attributes must be defined
|
||||
* against an explicit method or interface on the intercepted class.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Attributes detected that do not implement {@link ConfigAttribute} will be
|
||||
* ignored.
|
||||
* </p>
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MethodDefinitionAttributes implements MethodDefinitionSource {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Attributes attributes;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAttributes(Attributes attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
public ConfigAttributeDefinition getAttributes(MethodInvocation invocation) {
|
||||
ConfigAttributeDefinition definition = new ConfigAttributeDefinition();
|
||||
|
||||
Class interceptedClass = invocation.getMethod().getDeclaringClass();
|
||||
|
||||
// add the class level attributes for the implementing class
|
||||
addClassAttributes(definition, interceptedClass);
|
||||
|
||||
// add the class level attributes for the implemented interfaces
|
||||
addClassAttributes(definition, interceptedClass.getInterfaces());
|
||||
|
||||
// add the method level attributes for the implemented method
|
||||
addMethodAttributes(definition, invocation.getMethod());
|
||||
|
||||
// add the method level attributes for the implemented intreface methods
|
||||
addInterfaceMethodAttributes(definition, invocation.getMethod());
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
public Iterator getConfigAttributeDefinitions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void add(ConfigAttributeDefinition definition, Collection attribs) {
|
||||
for (Iterator iter = attribs.iterator(); iter.hasNext();) {
|
||||
Object o = (Object) iter.next();
|
||||
|
||||
if (o instanceof ConfigAttribute) {
|
||||
definition.addConfigAttribute((ConfigAttribute) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addClassAttributes(ConfigAttributeDefinition definition,
|
||||
Class clazz) {
|
||||
addClassAttributes(definition, new Class[] {clazz});
|
||||
}
|
||||
|
||||
private void addClassAttributes(ConfigAttributeDefinition definition,
|
||||
Class[] clazz) {
|
||||
for (int i = 0; i < clazz.length; i++) {
|
||||
Collection classAttributes = attributes.getAttributes(clazz[i]);
|
||||
|
||||
if (classAttributes != null) {
|
||||
add(definition, classAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addInterfaceMethodAttributes(
|
||||
ConfigAttributeDefinition definition, Method method) {
|
||||
Class[] interfaces = method.getDeclaringClass().getInterfaces();
|
||||
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
Class clazz = interfaces[i];
|
||||
|
||||
try {
|
||||
Method m = clazz.getDeclaredMethod(method.getName(),
|
||||
method.getParameterTypes());
|
||||
addMethodAttributes(definition, m);
|
||||
} catch (Exception e) {
|
||||
// this won't happen since we are getting a method from an interface that
|
||||
// the declaring class implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMethodAttributes(ConfigAttributeDefinition definition,
|
||||
Method method) {
|
||||
// add the method level attributes
|
||||
Collection methodAttributes = attributes.getAttributes(method);
|
||||
|
||||
if (methodAttributes != null) {
|
||||
add(definition, methodAttributes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,175 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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 net.sf.acegisecurity;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Stores a {@link ConfigAttributeDefinition} for each method signature defined
|
||||
* in a bean context.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MethodDefinitionMap implements MethodDefinitionSource {
|
||||
private static final Log logger = LogFactory.getLog(MethodDefinitionMap.class);
|
||||
|
||||
/** Map from Method to ApplicationDefinition */
|
||||
protected Map methodMap = new HashMap();
|
||||
|
||||
/** Map from Method to name pattern used for registration */
|
||||
private Map nameMap = new HashMap();
|
||||
|
||||
public ConfigAttributeDefinition getAttributes(MethodInvocation invocation) {
|
||||
return (ConfigAttributeDefinition) this.methodMap.get(invocation.getMethod());
|
||||
}
|
||||
|
||||
public Iterator getConfigAttributeDefinitions() {
|
||||
return methodMap.values().iterator();
|
||||
}
|
||||
|
||||
public int getMethodMapSize() {
|
||||
return this.methodMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required authorities for a secure method. Method names can end or
|
||||
* start with "" for matching multiple methods.
|
||||
*
|
||||
* @param method the method to be secured
|
||||
* @param attr required authorities associated with the method
|
||||
*/
|
||||
public void addSecureMethod(Method method, ConfigAttributeDefinition attr) {
|
||||
logger.info("Adding secure method [" + method + "] with attributes [" +
|
||||
attr + "]");
|
||||
this.methodMap.put(method, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required authorities for a secure method. Method names can end or
|
||||
* start with "" for matching multiple methods.
|
||||
*
|
||||
* @param name class and method name, separated by a dot
|
||||
* @param attr required authorities associated with the method
|
||||
*
|
||||
* @throws IllegalArgumentException DOCUMENT ME!
|
||||
*/
|
||||
public void addSecureMethod(String name, ConfigAttributeDefinition attr) {
|
||||
int lastDotIndex = name.lastIndexOf(".");
|
||||
|
||||
if (lastDotIndex == -1) {
|
||||
throw new IllegalArgumentException("'" + name +
|
||||
"' is not a valid method name: format is FQN.methodName");
|
||||
}
|
||||
|
||||
String className = name.substring(0, lastDotIndex);
|
||||
String methodName = name.substring(lastDotIndex + 1);
|
||||
|
||||
try {
|
||||
Class clazz = Class.forName(className, true,
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
addSecureMethod(clazz, methodName, attr);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new IllegalArgumentException("Class '" + className +
|
||||
"' not found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required authorities for a secure method. Method names can end or
|
||||
* start with "" for matching multiple methods.
|
||||
*
|
||||
* @param clazz target interface or class
|
||||
* @param mappedName mapped method name
|
||||
* @param attr required authorities associated with the method
|
||||
*
|
||||
* @throws IllegalArgumentException DOCUMENT ME!
|
||||
*/
|
||||
public void addSecureMethod(Class clazz, String mappedName,
|
||||
ConfigAttributeDefinition attr) {
|
||||
String name = clazz.getName() + '.' + mappedName;
|
||||
|
||||
logger.debug("Adding secure method [" + name + "] with attributes [" +
|
||||
attr + "]");
|
||||
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
List matchingMethods = new ArrayList();
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (methods[i].getName().equals(mappedName) ||
|
||||
isMatch(methods[i].getName(), mappedName)) {
|
||||
matchingMethods.add(methods[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingMethods.isEmpty()) {
|
||||
throw new IllegalArgumentException("Couldn't find method '" +
|
||||
mappedName + "' on " + clazz);
|
||||
}
|
||||
|
||||
// register all matching methods
|
||||
for (Iterator it = matchingMethods.iterator(); it.hasNext();) {
|
||||
Method method = (Method) it.next();
|
||||
String regMethodName = (String) this.nameMap.get(method);
|
||||
|
||||
if ((regMethodName == null) ||
|
||||
(!regMethodName.equals(name) &&
|
||||
(regMethodName.length() <= name.length()))) {
|
||||
// no already registered method name, or more specific
|
||||
// method name specification now -> (re-)register method
|
||||
if (regMethodName != null) {
|
||||
logger.debug("Replacing attributes for secure method [" +
|
||||
method + "]: current name [" + name +
|
||||
"] is more specific than [" + regMethodName + "]");
|
||||
}
|
||||
|
||||
this.nameMap.put(method, name);
|
||||
addSecureMethod(method, attr);
|
||||
} else {
|
||||
logger.debug("Keeping attributes for secure method [" + method +
|
||||
"]: current name [" + name +
|
||||
"] is not more specific than [" + regMethodName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the given method name matches the mapped name. The default
|
||||
* implementation checks for "xxx" and "xxx" matches.
|
||||
*
|
||||
* @param methodName the method name of the class
|
||||
* @param mappedName the name in the descriptor
|
||||
*
|
||||
* @return if the names match
|
||||
*/
|
||||
private boolean isMatch(String methodName, String mappedName) {
|
||||
return (mappedName.endsWith("*") &&
|
||||
methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) ||
|
||||
(mappedName.startsWith("*") &&
|
||||
methodName.endsWith(mappedName.substring(1, mappedName.length())));
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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 net.sf.acegisecurity;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Implemented by classes that store {@link ConfigAttributeDefinition}s and can
|
||||
* identify the appropriate <code>ConfigAttributeDefinition</code> that
|
||||
* applies for the current method call.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface MethodDefinitionSource {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param invocation the method being called
|
||||
*
|
||||
* @return the <code>ConfigAttributeDefinition</code> that applies to the
|
||||
* passed method call
|
||||
*/
|
||||
public ConfigAttributeDefinition getAttributes(MethodInvocation invocation);
|
||||
|
||||
/**
|
||||
* If available, all of the <code>ConfigAttributeDefinition</code>s defined
|
||||
* by the implementing class.
|
||||
*
|
||||
* @return an iterator over all the <code>ConfigAttributeDefinition</code>s
|
||||
* or <code>null</code> if unsupported
|
||||
*/
|
||||
public Iterator getConfigAttributeDefinitions();
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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 net.sf.acegisecurity;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* Property editor to assist with the setup of {@link MethodDefinitionSource}.
|
||||
*
|
||||
* <p>
|
||||
* The class creates and populates an {@link MethodDefinitionMap}.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MethodDefinitionSourceEditor extends PropertyEditorSupport {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MethodDefinitionSourceEditor.class);
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAsText(String s) throws IllegalArgumentException {
|
||||
MethodDefinitionMap source = new MethodDefinitionMap();
|
||||
|
||||
if ((s == null) || "".equals(s)) {
|
||||
// Leave value in property editor null
|
||||
} else {
|
||||
// Use properties editor to tokenize the string
|
||||
PropertiesEditor propertiesEditor = new PropertiesEditor();
|
||||
propertiesEditor.setAsText(s);
|
||||
|
||||
Properties props = (Properties) propertiesEditor.getValue();
|
||||
|
||||
// Now we have properties, process each one individually
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
|
||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
String value = props.getProperty(name);
|
||||
|
||||
// Convert value to series of security configuration attributes
|
||||
configAttribEd.setAsText(value);
|
||||
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd
|
||||
.getValue();
|
||||
|
||||
// Register name and attribute
|
||||
source.addSecureMethod(name, attr);
|
||||
}
|
||||
}
|
||||
|
||||
setValue(source);
|
||||
}
|
||||
}
|
|
@ -1,317 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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 net.sf.acegisecurity;
|
||||
|
||||
import net.sf.acegisecurity.context.Context;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Intercepts calls to an object and applies security.
|
||||
*
|
||||
* <p>
|
||||
* A method is treated as public unless it has one or more configuration
|
||||
* attributes defined via {@link
|
||||
* #setMethodDefinitionSource(MethodDefinitionSource)}. If public, no
|
||||
* authentication will be attempted, which means an unauthenticated {@link
|
||||
* Authentication} object may be present in the {@link ContextHolder} (if any
|
||||
* such an unauthenticated <code>Authentication</code> object exists, its
|
||||
* {@link Authentication#isAuthenticated()} method will return
|
||||
* <code>false</code> once the <code>SecurityInterceptor</code> has
|
||||
* intercepted the public method).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* For those methods to be secured by the interceptor, one or more
|
||||
* configuration attributes must be defined. These attributes are stored as
|
||||
* {@link ConfigAttribute} objects.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The presence of a configuration attribute for a given method will force
|
||||
* authentication to be attempted via the {@link AuthenticationManager}
|
||||
* configured against the interceptor. If successfully authenticated, the
|
||||
* configured {@link AccessDecisionManager} will be passed the {@link
|
||||
* ConfigAttributeDefinition} applicable for the method invocation, the
|
||||
* method invocation itself, and the <code>Authentication</code> object. The
|
||||
* <code>AccessDecisionManager</code> which will then make the authorization
|
||||
* decision.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* There shouldn't be any requirement to customise the behaviour of the
|
||||
* <code>SecurityInterceptor</code>, as all security decisions are made by the
|
||||
* <code>AuthenticationProvider</code> and <code>AccessDecisionManager</code>
|
||||
* interfaces, which can of course be replaced with different concrete
|
||||
* implementations.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityInterceptor implements MethodInterceptor, InitializingBean {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SecurityInterceptor.class);
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AccessDecisionManager accessDecisionManager;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private MethodDefinitionSource methodDefinitionSource;
|
||||
private RunAsManager runAsManager;
|
||||
private boolean validateConfigAttributes = true;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAccessDecisionManager(
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
this.accessDecisionManager = accessDecisionManager;
|
||||
}
|
||||
|
||||
public AccessDecisionManager getAccessDecisionManager() {
|
||||
return accessDecisionManager;
|
||||
}
|
||||
|
||||
public void setAuthenticationManager(AuthenticationManager newManager) {
|
||||
this.authenticationManager = newManager;
|
||||
}
|
||||
|
||||
public AuthenticationManager getAuthenticationManager() {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
|
||||
public void setMethodDefinitionSource(MethodDefinitionSource newSource) {
|
||||
this.methodDefinitionSource = newSource;
|
||||
}
|
||||
|
||||
public MethodDefinitionSource getMethodDefinitionSource() {
|
||||
return this.methodDefinitionSource;
|
||||
}
|
||||
|
||||
public void setRunAsManager(RunAsManager runAsManager) {
|
||||
this.runAsManager = runAsManager;
|
||||
}
|
||||
|
||||
public RunAsManager getRunAsManager() {
|
||||
return runAsManager;
|
||||
}
|
||||
|
||||
public void setValidateConfigAttributes(boolean validateConfigAttributes) {
|
||||
this.validateConfigAttributes = validateConfigAttributes;
|
||||
}
|
||||
|
||||
public boolean isValidateConfigAttributes() {
|
||||
return validateConfigAttributes;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.authenticationManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"An AuthenticationManager is required");
|
||||
}
|
||||
|
||||
if (this.accessDecisionManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"An AccessDecisionManager is required");
|
||||
}
|
||||
|
||||
if (this.runAsManager == null) {
|
||||
throw new IllegalArgumentException("A RunAsManager is required");
|
||||
}
|
||||
|
||||
if (this.methodDefinitionSource == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"A MethodDefinitionSource is required");
|
||||
}
|
||||
|
||||
if (this.validateConfigAttributes) {
|
||||
Iterator iter = this.methodDefinitionSource
|
||||
.getConfigAttributeDefinitions();
|
||||
|
||||
if (iter == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(
|
||||
"Could not validate configuration attributes as the MethodDefinitionSource did not return a ConfigAttributeDefinition Iterator");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Set set = new HashSet();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
|
||||
.next();
|
||||
Iterator attributes = def.getConfigAttributes();
|
||||
|
||||
while (attributes.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) attributes.next();
|
||||
|
||||
if (!this.runAsManager.supports(attr)
|
||||
&& !this.accessDecisionManager.supports(attr)) {
|
||||
set.add(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set.size() == 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Validated configuration attributes");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported configuration attributes: " + set.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the work of authenticating and authorizing the request. Throws
|
||||
* {@link AcegiSecurityException} and its subclasses.
|
||||
*
|
||||
* @param mi The method being invoked which requires a security decision
|
||||
*
|
||||
* @return The returned value from the method invocation
|
||||
*
|
||||
* @throws Throwable if any error occurs
|
||||
* @throws AuthenticationCredentialsNotFoundException if the
|
||||
* <code>ContextHolder</code> does not contain a valid
|
||||
* <code>SecureContext</code> which in turn contains an
|
||||
* <code>Authentication</code> object
|
||||
*/
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Intercepted request for method " + mi.getMethod());
|
||||
}
|
||||
|
||||
ConfigAttributeDefinition attr = this.methodDefinitionSource
|
||||
.getAttributes(mi);
|
||||
|
||||
if (attr != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Secure method configuration "
|
||||
+ attr.getConfigAttributes().toString());
|
||||
}
|
||||
|
||||
// Ensure ContextHolder presents a populated SecureContext
|
||||
if ((ContextHolder.getContext() == null)
|
||||
|| !(ContextHolder.getContext() instanceof SecureContext)) {
|
||||
throw new AuthenticationCredentialsNotFoundException(
|
||||
"A valid SecureContext was not provided in the RequestContext");
|
||||
}
|
||||
|
||||
SecureContext context = (SecureContext) ContextHolder.getContext();
|
||||
|
||||
// We check for just the property we're interested in (we do
|
||||
// not call Context.validate() like the ContextInterceptor)
|
||||
if (context.getAuthentication() == null) {
|
||||
throw new AuthenticationCredentialsNotFoundException(
|
||||
"Authentication credentials were not found in the SecureContext");
|
||||
}
|
||||
|
||||
// Attempt authentication
|
||||
Authentication authenticated = this.authenticationManager
|
||||
.authenticate(context.getAuthentication());
|
||||
authenticated.setAuthenticated(true);
|
||||
logger.debug("Authenticated: " + authenticated.toString());
|
||||
context.setAuthentication(authenticated);
|
||||
ContextHolder.setContext((Context) context);
|
||||
|
||||
// Attempt authorization
|
||||
this.accessDecisionManager.decide(authenticated, mi, attr);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authorization successful");
|
||||
}
|
||||
|
||||
// Attempt to run as a different user
|
||||
Authentication runAs = this.runAsManager.buildRunAs(authenticated,
|
||||
mi, attr);
|
||||
|
||||
if (runAs == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"RunAsManager did not change Authentication object");
|
||||
}
|
||||
|
||||
Object ret = mi.proceed();
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Switching to RunAs Authentication: "
|
||||
+ runAs.toString());
|
||||
}
|
||||
|
||||
context.setAuthentication(runAs);
|
||||
ContextHolder.setContext((Context) context);
|
||||
|
||||
Object ret = mi.proceed();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Reverting to original Authentication: "
|
||||
+ authenticated.toString());
|
||||
}
|
||||
|
||||
context.setAuthentication(authenticated);
|
||||
ContextHolder.setContext((Context) context);
|
||||
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Public method - authentication not attempted");
|
||||
}
|
||||
|
||||
// Set Authentication object (if it exists) to be unauthenticated
|
||||
if ((ContextHolder.getContext() != null)
|
||||
&& ContextHolder.getContext() instanceof SecureContext) {
|
||||
SecureContext context = (SecureContext) ContextHolder
|
||||
.getContext();
|
||||
|
||||
if (context.getAuthentication() != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Authentication object detected and tagged as unauthenticated");
|
||||
}
|
||||
|
||||
Authentication authenticated = context.getAuthentication();
|
||||
authenticated.setAuthenticated(false);
|
||||
context.setAuthentication(authenticated);
|
||||
ContextHolder.setContext((Context) context);
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = mi.proceed();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue