Adds spring.cloud.gateway.restrictive-property-accessor.enabled
To disable the restrictive accessor, set spring.cloud.gateway.restrictive-property-accessor.enabled=false.
This commit is contained in:
@@ -25,6 +25,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
@@ -38,6 +39,7 @@ import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.common.TemplateParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -65,7 +67,7 @@ public interface ShortcutConfigurable {
|
||||
}
|
||||
if (rawValue != null && rawValue.startsWith("#{") && entryValue.endsWith("}")) {
|
||||
// assume it's spel
|
||||
GatewayEvaluationContext context = new GatewayEvaluationContext(new BeanFactoryResolver(beanFactory));
|
||||
GatewayEvaluationContext context = new GatewayEvaluationContext(beanFactory);
|
||||
Expression expression = parser.parseExpression(entryValue, new TemplateParserContext());
|
||||
value = expression.getValue(context);
|
||||
}
|
||||
@@ -162,10 +164,20 @@ public interface ShortcutConfigurable {
|
||||
|
||||
private final BeanFactoryResolver beanFactoryResolver;
|
||||
|
||||
private SimpleEvaluationContext delegate = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
private final SimpleEvaluationContext delegate;
|
||||
|
||||
public GatewayEvaluationContext(BeanFactoryResolver beanFactoryResolver) {
|
||||
this.beanFactoryResolver = beanFactoryResolver;
|
||||
public GatewayEvaluationContext(BeanFactory beanFactory) {
|
||||
this.beanFactoryResolver = new BeanFactoryResolver(beanFactory);
|
||||
Environment env = beanFactory.getBean(Environment.class);
|
||||
boolean restrictive = env.getProperty("spring.cloud.gateway.restrictive-property-accessor.enabled",
|
||||
Boolean.class, true);
|
||||
if (restrictive) {
|
||||
delegate = SimpleEvaluationContext.forPropertyAccessors(new RestrictivePropertyAccessor())
|
||||
.withMethodResolvers((context, targetObject, name, argumentTypes) -> null).build();
|
||||
}
|
||||
else {
|
||||
delegate = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,4 +239,13 @@ public interface ShortcutConfigurable {
|
||||
|
||||
}
|
||||
|
||||
class RestrictivePropertyAccessor extends ReflectivePropertyAccessor {
|
||||
|
||||
@Override
|
||||
public boolean canRead(EvaluationContext context, Object target, String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -365,6 +365,12 @@
|
||||
"type": "java.lang.Integer",
|
||||
"description": "The order of RoutePredicateHandlerMapping.",
|
||||
"defaultValue": "1"
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.gateway.restrictive-property-accessor.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Restricts method and property access in SpEL.",
|
||||
"defaultValue": "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -44,6 +46,9 @@ public class ShortcutConfigurableTests {
|
||||
@Autowired
|
||||
BeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
ConfigurableEnvironment env;
|
||||
|
||||
private SpelExpressionParser parser;
|
||||
|
||||
@Test
|
||||
@@ -63,6 +68,42 @@ public class ShortcutConfigurableTests {
|
||||
}).isInstanceOf(SpelEvaluationException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDefaultTypeWithSpelAndInvalidPropertyReferenceFails() {
|
||||
TestPropertyValues.of("spring.cloud.gateway.restrictive-property-accessor.enabled=true").applyTo(env);
|
||||
parser = new SpelExpressionParser();
|
||||
ShortcutConfigurable shortcutConfigurable = new ShortcutConfigurable() {
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList("bean", "arg1");
|
||||
}
|
||||
};
|
||||
Map<String, String> args = new HashMap<>();
|
||||
args.put("barproperty", "#{@bar.getInt}");
|
||||
args.put("arg1", "val1");
|
||||
assertThatThrownBy(() -> {
|
||||
ShortcutType.DEFAULT.normalize(args, shortcutConfigurable, parser, this.beanFactory);
|
||||
}).isInstanceOf(SpelEvaluationException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDefaultTypeWithSpelAndInvalidMethodReferenceFails() {
|
||||
TestPropertyValues.of("ispring.cloud.gateway.restrictve-property-accessor.enabled=true").applyTo(env);
|
||||
parser = new SpelExpressionParser();
|
||||
ShortcutConfigurable shortcutConfigurable = new ShortcutConfigurable() {
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList("bean", "arg1");
|
||||
}
|
||||
};
|
||||
Map<String, String> args = new HashMap<>();
|
||||
args.put("barmethod", "#{@bar.myMethod}");
|
||||
args.put("arg1", "val1");
|
||||
assertThatThrownBy(() -> {
|
||||
ShortcutType.DEFAULT.normalize(args, shortcutConfigurable, parser, this.beanFactory);
|
||||
}).isInstanceOf(SpelEvaluationException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDefaultTypeWithSpel() {
|
||||
parser = new SpelExpressionParser();
|
||||
@@ -79,6 +120,40 @@ public class ShortcutConfigurableTests {
|
||||
assertThat(map).isNotNull().containsEntry("bean", 42).containsEntry("arg1", "val1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDefaultTypeWithSpelAndPropertyReferenceEnabled() {
|
||||
TestPropertyValues.of("spring.cloud.gateway.restrictive-property-accessor.enabled=false").applyTo(env);
|
||||
parser = new SpelExpressionParser();
|
||||
ShortcutConfigurable shortcutConfigurable = new ShortcutConfigurable() {
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList("bean", "arg1");
|
||||
}
|
||||
};
|
||||
Map<String, String> args = new HashMap<>();
|
||||
args.put("barproperty", "#{@bar.getInt}");
|
||||
args.put("arg1", "val1");
|
||||
Map<String, Object> map = ShortcutType.DEFAULT.normalize(args, shortcutConfigurable, parser, this.beanFactory);
|
||||
assertThat(map).isNotNull().containsEntry("barproperty", 42).containsEntry("arg1", "val1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeDefaultTypeWithSpelAndMethodReferenceEnabled() {
|
||||
TestPropertyValues.of("spring.cloud.gateway.restrictive-property-accessor.enabled=false").applyTo(env);
|
||||
parser = new SpelExpressionParser();
|
||||
ShortcutConfigurable shortcutConfigurable = new ShortcutConfigurable() {
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList("bean", "arg1");
|
||||
}
|
||||
};
|
||||
Map<String, String> args = new HashMap<>();
|
||||
args.put("barmethod", "#{@bar.myMethod}");
|
||||
args.put("arg1", "val1");
|
||||
Map<String, Object> map = ShortcutType.DEFAULT.normalize(args, shortcutConfigurable, parser, this.beanFactory);
|
||||
assertThat(map).isNotNull().containsEntry("barmethod", 42).containsEntry("arg1", "val1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testNormalizeGatherListTypeWithSpel() {
|
||||
@@ -155,6 +230,23 @@ public class ShortcutConfigurableTests {
|
||||
return 42;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Bar bar() {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class Bar {
|
||||
|
||||
public int getInt() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public int myMethod() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user