Remove support for deprecated Java SecurityManager (-> JDK 17 build compatibility)

Includes hard JDK 9+ API dependency in CGLIB ReflectUtils (Lookup.defineClass) and removal of OutputStream spy proxy usage (avoiding invalid Mockito proxy on JDK 17)

Closes gh-26901
This commit is contained in:
Juergen Hoeller
2021-09-15 15:30:25 +02:00
parent 0640da74bc
commit cf2429b0f0
47 changed files with 147 additions and 2078 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,6 @@ package org.springframework.beans;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.Property;
@@ -69,12 +64,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Nullable
private CachedIntrospectionResults cachedIntrospectionResults;
/**
* The security context used for invoking the property methods.
*/
@Nullable
private AccessControlContext acc;
/**
* Create a new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
@@ -131,7 +120,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
*/
private BeanWrapperImpl(Object object, String nestedPath, BeanWrapperImpl parent) {
super(object, nestedPath, parent);
setSecurityContext(parent.acc);
}
@@ -176,23 +164,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
return this.cachedIntrospectionResults;
}
/**
* Set the security context used during the invocation of the wrapped instance methods.
* Can be null.
*/
public void setSecurityContext(@Nullable AccessControlContext acc) {
this.acc = acc;
}
/**
* Return the security context used during the invocation of the wrapped instance methods.
* Can be null.
*/
@Nullable
public AccessControlContext getSecurityContext() {
return this.acc;
}
/**
* Convert the given value for the specified property to the latter's type.
@@ -290,23 +261,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Nullable
public Object getValue() throws Exception {
Method readMethod = this.pd.getReadMethod();
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(readMethod);
return null;
});
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
ReflectionUtils.makeAccessible(readMethod);
return readMethod.invoke(getWrappedInstance(), (Object[]) null);
}
ReflectionUtils.makeAccessible(readMethod);
return readMethod.invoke(getWrappedInstance(), (Object[]) null);
}
@Override
@@ -314,23 +270,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
package org.springframework.beans.factory.config;
import java.beans.PropertyEditor;
import java.security.AccessControlContext;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
@@ -291,13 +290,6 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
*/
ApplicationStartup getApplicationStartup();
/**
* Provides a security access control context relevant to this factory.
* @return the applicable AccessControlContext (never {@code null})
* @since 3.0
*/
AccessControlContext getAccessControlContext();
/**
* Copy all relevant configuration from the given other factory.
* <p>Should include all standard configuration settings as well as

View File

@@ -21,10 +21,6 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -387,15 +383,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
}
else {
Object bean;
if (System.getSecurityManager() != null) {
bean = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(bd, null, this),
getAccessControlContext());
}
else {
bean = getInstantiationStrategy().instantiate(bd, null, this);
}
Object bean = getInstantiationStrategy().instantiate(bd, null, this);
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
return bean;
}
@@ -463,8 +451,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
@Override
public void destroyBean(Object existingBean) {
new DisposableBeanAdapter(
existingBean, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
new DisposableBeanAdapter(existingBean, getBeanPostProcessorCache().destructionAware).destroy();
}
@@ -1316,15 +1303,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
@@ -1655,10 +1634,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
@@ -1781,15 +1756,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
@@ -1848,20 +1815,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null && bean.getClass() != NullBean.class) {
@@ -1910,28 +1864,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
else {
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,6 @@
package org.springframework.beans.factory.support;
import java.beans.PropertyEditor;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -166,10 +161,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** Map from scope identifier String to corresponding Scope. */
private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
/** Security context used when running with a SecurityManager. */
@Nullable
private SecurityContextProvider securityContextProvider;
/** Map from bean name to merged RootBeanDefinition. */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
@@ -495,17 +486,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
if (isFactoryBean(beanName, mbd)) {
FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(
(PrivilegedAction<Boolean>) () ->
((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
!fb.isSingleton()),
getAccessControlContext());
}
else {
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
!fb.isSingleton());
}
return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
!fb.isSingleton());
}
else {
return false;
@@ -1054,15 +1036,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.scopes.get(scopeName);
}
/**
* Set the security context provider for this bean factory. If a security manager
* is set, interaction with the user code will be executed using the privileged
* of the provided security context.
*/
public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
this.securityContextProvider = securityProvider;
}
@Override
public void setApplicationStartup(ApplicationStartup applicationStartup) {
Assert.notNull(applicationStartup, "applicationStartup should not be null");
@@ -1074,17 +1047,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.applicationStartup;
}
/**
* Delegate the creation of the access control context to the
* {@link #setSecurityContextProvider SecurityContextProvider}.
*/
@Override
public AccessControlContext getAccessControlContext() {
return (this.securityContextProvider != null ?
this.securityContextProvider.getAccessControlContext() :
AccessController.getContext());
}
@Override
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
Assert.notNull(otherFactory, "BeanFactory must not be null");
@@ -1099,7 +1061,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.scopes.putAll(otherAbstractFactory.scopes);
this.securityContextProvider = otherAbstractFactory.securityContextProvider;
}
else {
setTypeConverter(otherFactory.getTypeConverter());
@@ -1222,7 +1183,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
*/
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware).destroy();
}
@Override
@@ -1526,17 +1487,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
}
catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
return doResolveBeanClass(mbd, typesToMatch);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
@@ -1925,14 +1876,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @see #registerDependentBean
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware));
}
else {
// A bean with a custom scope...
@@ -1941,7 +1891,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware));
}
}
}

View File

@@ -22,8 +22,6 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -302,14 +300,7 @@ class ConstructorResolver {
try {
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
@@ -365,15 +356,8 @@ class ConstructorResolver {
* Called as the starting point for factory method determination.
*/
private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Method[]>) () ->
(mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()));
}
else {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
/**
@@ -643,16 +627,8 @@ class ConstructorResolver {
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
this.beanFactory.getAccessControlContext());
}
else {
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,6 @@ import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -296,15 +294,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) {
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
if (autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
return null;
}, getAccessControlContext());
}
else {
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
}
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
}
this.autowireCandidateResolver = autowireCandidateResolver;
}
@@ -925,16 +915,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
boolean isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
if (isEagerInit) {
getBean(beanName);
}
@@ -953,15 +935,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
}
}

View File

@@ -19,11 +19,6 @@ package org.springframework.beans.factory.support;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
@@ -76,9 +71,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private final boolean nonPublicAccessAllowed;
@Nullable
private final AccessControlContext acc;
@Nullable
private String destroyMethodName;
@@ -98,7 +90,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* (potentially DestructionAwareBeanPostProcessor), if any
*/
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
List<DestructionAwareBeanPostProcessor> postProcessors) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
@@ -106,7 +98,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
@@ -143,15 +134,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param postProcessors the List of BeanPostProcessors
* (potentially DestructionAwareBeanPostProcessor), if any
*/
public DisposableBeanAdapter(
Object bean, List<DestructionAwareBeanPostProcessor> postProcessors, AccessControlContext acc) {
public DisposableBeanAdapter(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = bean.getClass().getName();
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
this.nonPublicAccessAllowed = true;
this.acc = acc;
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
@@ -166,7 +154,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
this.beanName = beanName;
this.invokeDisposableBean = invokeDisposableBean;
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
this.acc = null;
this.destroyMethodName = destroyMethodName;
this.beanPostProcessors = postProcessors;
}
@@ -190,15 +177,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
((DisposableBean) this.bean).destroy();
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
@@ -226,12 +205,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
@Nullable
private Method determineDestroyMethod(String name) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Method>) () -> findDestroyMethod(name));
}
else {
return findDestroyMethod(name);
}
return findDestroyMethod(name);
}
catch (IllegalArgumentException ex) {
throw new BeanDefinitionValidationException("Could not find unique destroy method on bean with name '" +
@@ -263,23 +237,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
"' on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(destroyMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
destroyMethod.invoke(this.bean, args), this.acc);
}
catch (PrivilegedActionException pax) {
throw (InvocationTargetException) pax.getException();
}
}
else {
ReflectionUtils.makeAccessible(destroyMethod);
destroyMethod.invoke(this.bean, args);
}
ReflectionUtils.makeAccessible(destroyMethod);
destroyMethod.invoke(this.bean, args);
}
catch (InvocationTargetException ex) {
String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" +

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,6 @@
package org.springframework.beans.factory.support;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -56,13 +51,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
@Nullable
protected Class<?> getTypeForFactoryBean(FactoryBean<?> factoryBean) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(
(PrivilegedAction<Class<?>>) factoryBean::getObjectType, getAccessControlContext());
}
else {
return factoryBean.getObjectType();
}
return factoryBean.getObjectType();
}
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
@@ -156,18 +145,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
object = factory.getObject();
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
@@ -239,14 +217,4 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
}
}
/**
* Return the security context for this bean factory. If a security manager
* is set, interaction with the user code will be executed using the privileged
* of the security context returned by this method.
* @see AccessController#getContext()
*/
protected AccessControlContext getAccessControlContext() {
return AccessController.getContext();
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support;
import java.security.AccessControlContext;
/**
* Provider of the security context of the code running inside the bean factory.
*
* @author Costin Leau
* @since 3.0
*/
public interface SecurityContextProvider {
/**
* Provides a security access control context relevant to a bean factory.
* @return bean factory security control context
*/
AccessControlContext getAccessControlContext();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,9 +19,6 @@ package org.springframework.beans.factory.support;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
@@ -70,13 +67,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
constructorToUse = clazz.getDeclaredConstructor();
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
@@ -107,13 +98,6 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
return BeanUtils.instantiateClass(ctor, args);
}
else {
@@ -138,15 +122,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
ReflectionUtils.makeAccessible(factoryMethod);
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support;
import java.security.AccessControlContext;
import java.security.AccessController;
import org.springframework.lang.Nullable;
/**
* Simple {@link SecurityContextProvider} implementation.
*
* @author Costin Leau
* @since 3.0
*/
public class SimpleSecurityContextProvider implements SecurityContextProvider {
@Nullable
private final AccessControlContext acc;
/**
* Construct a new {@code SimpleSecurityContextProvider} instance.
* <p>The security context will be retrieved on each call from the current
* thread.
*/
public SimpleSecurityContextProvider() {
this(null);
}
/**
* Construct a new {@code SimpleSecurityContextProvider} instance.
* <p>If the given control context is null, the security context will be
* retrieved on each call from the current thread.
* @param acc access control context (can be {@code null})
* @see AccessController#getContext()
*/
public SimpleSecurityContextProvider(@Nullable AccessControlContext acc) {
this.acc = acc;
}
@Override
public AccessControlContext getAccessControlContext() {
return (this.acc != null ? this.acc : AccessController.getContext());
}
}

View File

@@ -20,10 +20,6 @@ import java.io.Closeable;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Arrays;
@@ -41,7 +37,6 @@ import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Priority;
import javax.security.auth.Subject;
import org.junit.jupiter.api.Test;
@@ -90,7 +85,6 @@ import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.testfixture.io.SerializationTestUtils;
import org.springframework.core.testfixture.security.TestPrincipal;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;
@@ -2602,22 +2596,6 @@ class DefaultListableBeanFactoryTests {
}
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
void initSecurityAwarePrototypeBean() {
RootBeanDefinition bd = new RootBeanDefinition(TestSecuredBean.class);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.setInitMethodName("init");
lbf.registerBeanDefinition("test", bd);
final Subject subject = new Subject();
subject.getPrincipals().add(new TestPrincipal("user1"));
TestSecuredBean bean = (TestSecuredBean) Subject.doAsPrivileged(subject,
(PrivilegedAction) () -> lbf.getBean("test"), null);
assertThat(bean).isNotNull();
assertThat(bean.getUserName()).isEqualTo("user1");
}
@Test
void containsBeanReturnsTrueEvenForAbstractBeanDefinition() {
lbf.registerBeanDefinition("abs", BeanDefinitionBuilder
@@ -3058,37 +3036,6 @@ class DefaultListableBeanFactoryTests {
}
@SuppressWarnings("unused")
private static class TestSecuredBean {
private String userName;
void init() {
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
if (subject == null) {
return;
}
setNameFromPrincipal(subject.getPrincipals());
}
private void setNameFromPrincipal(Set<Principal> principals) {
if (principals == null) {
return;
}
for (Iterator<Principal> it = principals.iterator(); it.hasNext();) {
Principal p = it.next();
this.userName = p.getName();
return;
}
}
public String getUserName() {
return this.userName;
}
}
@SuppressWarnings("unused")
private static class KnowsIfInstantiated {
@@ -3105,7 +3052,6 @@ class DefaultListableBeanFactoryTests {
public KnowsIfInstantiated() {
instantiated = true;
}
}

View File

@@ -1,479 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.Policy;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.PropertyPermission;
import java.util.Set;
import java.util.function.Consumer;
import javax.security.auth.AuthPermission;
import javax.security.auth.Subject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.SecurityContextProvider;
import org.springframework.beans.factory.support.security.support.ConstructorBean;
import org.springframework.beans.factory.support.security.support.CustomCallbackBean;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.NestedRuntimeException;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.testfixture.security.TestPrincipal;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Security test case. Checks whether the container uses its privileges for its
* internal work but does not leak them when touching/calling user code.
*
* <p>The first half of the test case checks that permissions are downgraded when
* calling user code while the second half that the caller code permission get
* through and Spring doesn't override the permission stack.
*
* @author Costin Leau
*/
public class CallbacksSecurityTests {
private DefaultListableBeanFactory beanFactory;
private SecurityContextProvider provider;
@SuppressWarnings("unused")
private static class NonPrivilegedBean {
private String expectedName;
public static boolean destroyed = false;
public NonPrivilegedBean(String expected) {
this.expectedName = expected;
checkCurrentContext();
}
public void init() {
checkCurrentContext();
}
public void destroy() {
checkCurrentContext();
destroyed = true;
}
public void setProperty(Object value) {
checkCurrentContext();
}
public Object getProperty() {
checkCurrentContext();
return null;
}
public void setListProperty(Object value) {
checkCurrentContext();
}
public Object getListProperty() {
checkCurrentContext();
return null;
}
private void checkCurrentContext() {
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
}
}
@SuppressWarnings("unused")
private static class NonPrivilegedSpringCallbacksBean implements
InitializingBean, DisposableBean, BeanClassLoaderAware,
BeanFactoryAware, BeanNameAware {
private String expectedName;
public static boolean destroyed = false;
public NonPrivilegedSpringCallbacksBean(String expected) {
this.expectedName = expected;
checkCurrentContext();
}
@Override
public void afterPropertiesSet() {
checkCurrentContext();
}
@Override
public void destroy() {
checkCurrentContext();
destroyed = true;
}
@Override
public void setBeanName(String name) {
checkCurrentContext();
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
checkCurrentContext();
}
@Override
public void setBeanFactory(BeanFactory beanFactory)
throws BeansException {
checkCurrentContext();
}
private void checkCurrentContext() {
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
}
}
@SuppressWarnings({ "unused", "rawtypes" })
private static class NonPrivilegedFactoryBean implements SmartFactoryBean {
private String expectedName;
public NonPrivilegedFactoryBean(String expected) {
this.expectedName = expected;
checkCurrentContext();
}
@Override
public boolean isEagerInit() {
checkCurrentContext();
return false;
}
@Override
public boolean isPrototype() {
checkCurrentContext();
return true;
}
@Override
public Object getObject() throws Exception {
checkCurrentContext();
return new Object();
}
@Override
public Class getObjectType() {
checkCurrentContext();
return Object.class;
}
@Override
public boolean isSingleton() {
checkCurrentContext();
return false;
}
private void checkCurrentContext() {
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
}
}
@SuppressWarnings("unused")
private static class NonPrivilegedFactory {
private final String expectedName;
public NonPrivilegedFactory(String expected) {
this.expectedName = expected;
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
}
public static Object makeStaticInstance(String expectedName) {
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
return new Object();
}
public Object makeInstance() {
assertThat(getCurrentSubjectName()).isEqualTo(expectedName);
return new Object();
}
}
private static String getCurrentSubjectName() {
final AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
Subject subject = Subject.getSubject(acc);
if (subject == null) {
return null;
}
Set<Principal> principals = subject.getPrincipals();
if (principals == null) {
return null;
}
for (Principal p : principals) {
return p.getName();
}
return null;
}
});
}
public CallbacksSecurityTests() {
// setup security
if (System.getSecurityManager() == null) {
Policy policy = Policy.getPolicy();
URL policyURL = getClass()
.getResource(
"/org/springframework/beans/factory/support/security/policy.all");
System.setProperty("java.security.policy", policyURL.toString());
System.setProperty("policy.allowSystemProperty", "true");
policy.refresh();
System.setSecurityManager(new SecurityManager());
}
}
@BeforeEach
public void setUp() throws Exception {
final ProtectionDomain empty = new ProtectionDomain(null,
new Permissions());
provider = new SecurityContextProvider() {
private final AccessControlContext acc = new AccessControlContext(
new ProtectionDomain[] { empty });
@Override
public AccessControlContext getAccessControlContext() {
return acc;
}
};
DefaultResourceLoader drl = new DefaultResourceLoader();
Resource config = drl
.getResource("/org/springframework/beans/factory/support/security/callbacks.xml");
beanFactory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(config);
beanFactory.setSecurityContextProvider(provider);
}
@Test
public void testSecuritySanity() throws Exception {
AccessControlContext acc = provider.getAccessControlContext();
assertThatExceptionOfType(SecurityException.class).as(
"Acc should not have any permissions").isThrownBy(() ->
acc.checkPermission(new PropertyPermission("*", "read")));
CustomCallbackBean bean = new CustomCallbackBean();
Method method = bean.getClass().getMethod("destroy");
method.setAccessible(true);
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
method.invoke(bean);
return null;
}, acc));
Class<ConstructorBean> cl = ConstructorBean.class;
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
cl.newInstance(), acc));
}
@Test
public void testSpringInitBean() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("spring-init"))
.withCauseInstanceOf(SecurityException.class);
}
@Test
public void testCustomInitBean() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("custom-init"))
.withCauseInstanceOf(SecurityException.class);
}
@Test
public void testSpringDestroyBean() throws Exception {
beanFactory.getBean("spring-destroy");
beanFactory.destroySingletons();
assertThat(System.getProperty("security.destroy")).isNull();
}
@Test
public void testCustomDestroyBean() throws Exception {
beanFactory.getBean("custom-destroy");
beanFactory.destroySingletons();
assertThat(System.getProperty("security.destroy")).isNull();
}
@Test
public void testCustomFactoryObject() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("spring-factory"))
.withCauseInstanceOf(SecurityException.class);
}
@Test
public void testCustomFactoryType() throws Exception {
assertThat(beanFactory.getType("spring-factory")).isNull();
assertThat(System.getProperty("factory.object.type")).isNull();
}
@Test
public void testCustomStaticFactoryMethod() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("custom-static-factory-method"))
.satisfies(mostSpecificCauseOf(SecurityException.class));
}
@Test
public void testCustomInstanceFactoryMethod() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("custom-factory-method"))
.satisfies(mostSpecificCauseOf(SecurityException.class));
}
@Test
public void testTrustedFactoryMethod() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("privileged-static-factory-method"))
.satisfies(mostSpecificCauseOf(SecurityException.class));
}
@Test
public void testConstructor() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("constructor"))
.satisfies(mostSpecificCauseOf(SecurityException.class));
}
@Test
public void testContainerPrivileges() throws Exception {
AccessControlContext acc = provider.getAccessControlContext();
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
beanFactory.getBean("working-factory-method");
beanFactory.getBean("container-execution");
return null;
}
}, acc);
}
@Test
public void testPropertyInjection() throws Exception {
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
beanFactory.getBean("property-injection"))
.withMessageContaining("security");
beanFactory.getBean("working-property-injection");
}
@Test
public void testInitSecurityAwarePrototypeBean() {
final DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
BeanDefinitionBuilder bdb = BeanDefinitionBuilder
.genericBeanDefinition(NonPrivilegedBean.class).setScope(
BeanDefinition.SCOPE_PROTOTYPE)
.setInitMethodName("init").setDestroyMethodName("destroy")
.addConstructorArgValue("user1");
lbf.registerBeanDefinition("test", bdb.getBeanDefinition());
final Subject subject = new Subject();
subject.getPrincipals().add(new TestPrincipal("user1"));
NonPrivilegedBean bean = Subject.doAsPrivileged(
subject, new PrivilegedAction<NonPrivilegedBean>() {
@Override
public NonPrivilegedBean run() {
return lbf.getBean("test", NonPrivilegedBean.class);
}
}, null);
assertThat(bean).isNotNull();
}
@Test
public void testTrustedExecution() throws Exception {
beanFactory.setSecurityContextProvider(null);
Permissions perms = new Permissions();
perms.add(new AuthPermission("getSubject"));
ProtectionDomain pd = new ProtectionDomain(null, perms);
new AccessControlContext(new ProtectionDomain[] { pd });
final Subject subject = new Subject();
subject.getPrincipals().add(new TestPrincipal("user1"));
// request the beans from non-privileged code
Subject.doAsPrivileged(subject, new PrivilegedAction<Object>() {
@Override
public Object run() {
// sanity check
assertThat(getCurrentSubjectName()).isEqualTo("user1");
assertThat(NonPrivilegedBean.destroyed).isEqualTo(false);
beanFactory.getBean("trusted-spring-callbacks");
beanFactory.getBean("trusted-custom-init-destroy");
// the factory is a prototype - ask for multiple instances
beanFactory.getBean("trusted-spring-factory");
beanFactory.getBean("trusted-spring-factory");
beanFactory.getBean("trusted-spring-factory");
beanFactory.getBean("trusted-factory-bean");
beanFactory.getBean("trusted-static-factory-method");
beanFactory.getBean("trusted-factory-method");
beanFactory.getBean("trusted-property-injection");
beanFactory.getBean("trusted-working-property-injection");
beanFactory.destroySingletons();
assertThat(NonPrivilegedBean.destroyed).isEqualTo(true);
return null;
}
}, provider.getAccessControlContext());
}
private <E extends NestedRuntimeException> Consumer<E> mostSpecificCauseOf(Class<? extends Throwable> type) {
return ex -> assertThat(ex.getMostSpecificCause()).isInstanceOf(type);
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
/**
* @author Costin Leau
*/
public class ConstructorBean {
public ConstructorBean() {
System.getProperties();
}
public ConstructorBean(Object obj) {
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
/**
* @author Costin Leau
*/
public class CustomCallbackBean {
public void init() {
System.getProperties();
}
public void destroy() {
System.setProperty("security.destroy", "true");
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
/**
* @author Costin Leau
*/
public class CustomFactoryBean implements FactoryBean<Properties> {
@Override
public Properties getObject() throws Exception {
return System.getProperties();
}
@Override
public Class<Properties> getObjectType() {
System.setProperty("factory.object.type", "true");
return Properties.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
import org.springframework.beans.factory.DisposableBean;
/**
* @author Costin Leau
*/
public class DestroyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.setProperty("security.destroy", "true");
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
/**
* @author Costin Leau
*/
public class FactoryBean {
public static Object makeStaticInstance() {
System.getProperties();
return new Object();
}
protected static Object protectedStaticInstance() {
return "protectedStaticInstance";
}
public Object makeInstance() {
System.getProperties();
return new Object();
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Costin Leau
*/
public class InitBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.getProperties();
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.beans.factory.support.security.support;
/**
* @author Costin Leau
*/
public class PropertyBean {
public void setSecurityProperty(Object property) {
System.getProperties();
}
public void setProperty(Object property) {
}
}

View File

@@ -502,7 +502,7 @@ class CustomEditorTests {
CharBean cb = new CharBean();
BeanWrapper bw = new BeanWrapperImpl(cb);
bw.setPropertyValue("myChar", new Character('c'));
bw.setPropertyValue("myChar", Character.valueOf('c'));
assertThat(cb.getMyChar()).isEqualTo('c');
bw.setPropertyValue("myChar", "c");