Skip to content

Commit 7560a32

Browse files
committed
Polish InterceptMethodsBeanDefinitionDecorator
Issue gh-11328
1 parent ba0f8ec commit 7560a32

File tree

1 file changed

+126
-117
lines changed

1 file changed

+126
-117
lines changed

config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java

Lines changed: 126 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -69,27 +69,26 @@
6969
*/
7070
public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator {
7171

72+
private final InternalAuthorizationManagerInterceptMethodsBeanDefinitionDecorator authorizationManagerDelegate =
73+
new InternalAuthorizationManagerInterceptMethodsBeanDefinitionDecorator();
7274
private final BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
7375

7476
@Override
7577
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
78+
if (this.authorizationManagerDelegate.supports(node)) {
79+
return this.authorizationManagerDelegate.decorate(node, definition, parserContext);
80+
}
7681
MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext);
7782
return this.delegate.decorate(node, definition, parserContext);
7883
}
7984

80-
/**
81-
* This is the real class which does the work. We need access to the ParserContext in
82-
* order to do bean registration.
83-
*/
84-
static class InternalInterceptMethodsBeanDefinitionDecorator
85+
static class InternalAuthorizationManagerInterceptMethodsBeanDefinitionDecorator
8586
extends AbstractInterceptorDrivenBeanDefinitionDecorator {
8687

8788
static final String ATT_METHOD = "method";
8889

8990
static final String ATT_ACCESS = "access";
9091

91-
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
92-
9392
private static final String ATT_USE_AUTHORIZATION_MGR = "use-authorization-manager";
9493

9594
private static final String ATT_AUTHORIZATION_MGR = "authorization-manager-ref";
@@ -99,16 +98,6 @@ static class InternalInterceptMethodsBeanDefinitionDecorator
9998
@Override
10099
protected BeanDefinition createInterceptorDefinition(Node node) {
101100
Element interceptMethodsElt = (Element) node;
102-
if (Boolean.parseBoolean(interceptMethodsElt.getAttribute(ATT_USE_AUTHORIZATION_MGR))) {
103-
return createAuthorizationManagerInterceptorDefinition(interceptMethodsElt);
104-
}
105-
if (StringUtils.hasText(interceptMethodsElt.getAttribute(ATT_AUTHORIZATION_MGR))) {
106-
return createAuthorizationManagerInterceptorDefinition(interceptMethodsElt);
107-
}
108-
return createMethodSecurityInterceptorDefinition(interceptMethodsElt);
109-
}
110-
111-
private BeanDefinition createAuthorizationManagerInterceptorDefinition(Element interceptMethodsElt) {
112101
BeanDefinitionBuilder interceptor = BeanDefinitionBuilder
113102
.rootBeanDefinition(AuthorizationManagerBeforeMethodInterceptor.class);
114103
interceptor.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
@@ -122,6 +111,14 @@ private BeanDefinition createAuthorizationManagerInterceptorDefinition(Element i
122111
.addConstructorArgValue(authorizationManager(managers)).getBeanDefinition();
123112
}
124113

114+
boolean supports(Node node) {
115+
Element interceptMethodsElt = (Element) node;
116+
if (Boolean.parseBoolean(interceptMethodsElt.getAttribute(ATT_USE_AUTHORIZATION_MGR))) {
117+
return true;
118+
}
119+
return StringUtils.hasText(interceptMethodsElt.getAttribute(ATT_AUTHORIZATION_MGR));
120+
}
121+
125122
private Pointcut pointcut(Element interceptorElt, Element protectElt) {
126123
String method = protectElt.getAttribute(ATT_METHOD);
127124
Class<?> javaType = javaType(interceptorElt, method);
@@ -159,7 +156,118 @@ private Class<?> javaType(Element interceptMethodsElt, String method) {
159156
return ClassUtils.resolveClassName(typeName, this.beanClassLoader);
160157
}
161158

162-
private BeanDefinition createMethodSecurityInterceptorDefinition(Element interceptMethodsElt) {
159+
private static class PrefixBasedMethodMatcher implements MethodMatcher, Pointcut {
160+
161+
private final ClassFilter classFilter;
162+
163+
private final String methodPrefix;
164+
165+
PrefixBasedMethodMatcher(Class<?> javaType, String methodPrefix) {
166+
this.classFilter = new RootClassFilter(javaType);
167+
this.methodPrefix = methodPrefix;
168+
}
169+
170+
@Override
171+
public ClassFilter getClassFilter() {
172+
return this.classFilter;
173+
}
174+
175+
@Override
176+
public MethodMatcher getMethodMatcher() {
177+
return this;
178+
}
179+
180+
@Override
181+
public boolean matches(Method method, Class<?> targetClass) {
182+
return matches(this.methodPrefix, method.getName());
183+
}
184+
185+
@Override
186+
public boolean isRuntime() {
187+
return false;
188+
}
189+
190+
@Override
191+
public boolean matches(Method method, Class<?> targetClass, Object... args) {
192+
return matches(this.methodPrefix, method.getName());
193+
}
194+
195+
private boolean matches(String mappedName, String methodName) {
196+
boolean equals = methodName.equals(mappedName);
197+
return equals || prefixMatches(mappedName, methodName) || suffixMatches(mappedName, methodName);
198+
}
199+
200+
private boolean prefixMatches(String mappedName, String methodName) {
201+
return mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1));
202+
}
203+
204+
private boolean suffixMatches(String mappedName, String methodName) {
205+
return mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1));
206+
}
207+
208+
}
209+
210+
private static class PointcutMatchingAuthorizationManager implements AuthorizationManager<MethodInvocation> {
211+
212+
private final Map<Pointcut, AuthorizationManager<MethodInvocation>> managers;
213+
214+
PointcutMatchingAuthorizationManager(Map<Pointcut, AuthorizationManager<MethodInvocation>> managers) {
215+
this.managers = managers;
216+
}
217+
218+
@Override
219+
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation object) {
220+
for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
221+
Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
222+
if (entry.getKey().getClassFilter().matches(targetClass)
223+
&& entry.getKey().getMethodMatcher().matches(object.getMethod(), targetClass)) {
224+
return entry.getValue().check(authentication, object);
225+
}
226+
}
227+
return new AuthorizationDecision(false);
228+
}
229+
230+
}
231+
232+
private static class MethodExpressionAuthorizationManager implements AuthorizationManager<MethodInvocation> {
233+
234+
private final Expression expression;
235+
236+
private SecurityExpressionHandler<MethodInvocation> expressionHandler = new DefaultMethodSecurityExpressionHandler();
237+
238+
MethodExpressionAuthorizationManager(Expression expression) {
239+
this.expression = expression;
240+
}
241+
242+
@Override
243+
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation invocation) {
244+
EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, invocation);
245+
boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
246+
return new ExpressionAuthorizationDecision(granted, this.expression);
247+
}
248+
249+
void setExpressionHandler(SecurityExpressionHandler<MethodInvocation> expressionHandler) {
250+
this.expressionHandler = expressionHandler;
251+
}
252+
253+
}
254+
}
255+
/**
256+
* This is the real class which does the work. We need access to the ParserContext in
257+
* order to do bean registration.
258+
*/
259+
static class InternalInterceptMethodsBeanDefinitionDecorator
260+
extends AbstractInterceptorDrivenBeanDefinitionDecorator {
261+
262+
static final String ATT_METHOD = "method";
263+
264+
static final String ATT_ACCESS = "access";
265+
266+
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
267+
268+
@Override
269+
protected BeanDefinition createInterceptorDefinition(Node node) {
270+
Element interceptMethodsElt = (Element) node;
163271
BeanDefinitionBuilder interceptor = BeanDefinitionBuilder
164272
.rootBeanDefinition(MethodSecurityInterceptor.class);
165273
// Default to autowiring to pick up after invocation mgr
@@ -197,103 +305,4 @@ private BeanDefinition createMethodSecurityInterceptorDefinition(Element interce
197305

198306
}
199307

200-
private static class PrefixBasedMethodMatcher implements MethodMatcher, Pointcut {
201-
202-
private final ClassFilter classFilter;
203-
204-
private final Class<?> javaType;
205-
206-
private final String methodPrefix;
207-
208-
PrefixBasedMethodMatcher(Class<?> javaType, String methodPrefix) {
209-
this.classFilter = new RootClassFilter(javaType);
210-
this.javaType = javaType;
211-
this.methodPrefix = methodPrefix;
212-
}
213-
214-
@Override
215-
public ClassFilter getClassFilter() {
216-
return this.classFilter;
217-
}
218-
219-
@Override
220-
public MethodMatcher getMethodMatcher() {
221-
return this;
222-
}
223-
224-
@Override
225-
public boolean matches(Method method, Class<?> targetClass) {
226-
return matches(this.methodPrefix, method.getName());
227-
}
228-
229-
@Override
230-
public boolean isRuntime() {
231-
return false;
232-
}
233-
234-
@Override
235-
public boolean matches(Method method, Class<?> targetClass, Object... args) {
236-
return matches(this.methodPrefix, method.getName());
237-
}
238-
239-
private boolean matches(String mappedName, String methodName) {
240-
boolean equals = methodName.equals(mappedName);
241-
return equals || prefixMatches(mappedName, methodName) || suffixMatches(mappedName, methodName);
242-
}
243-
244-
private boolean prefixMatches(String mappedName, String methodName) {
245-
return mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1));
246-
}
247-
248-
private boolean suffixMatches(String mappedName, String methodName) {
249-
return mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1));
250-
}
251-
252-
}
253-
254-
private static class PointcutMatchingAuthorizationManager implements AuthorizationManager<MethodInvocation> {
255-
256-
private final Map<Pointcut, AuthorizationManager<MethodInvocation>> managers;
257-
258-
PointcutMatchingAuthorizationManager(Map<Pointcut, AuthorizationManager<MethodInvocation>> managers) {
259-
this.managers = managers;
260-
}
261-
262-
@Override
263-
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation object) {
264-
for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
265-
Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
266-
if (entry.getKey().getClassFilter().matches(targetClass)
267-
&& entry.getKey().getMethodMatcher().matches(object.getMethod(), targetClass)) {
268-
return entry.getValue().check(authentication, object);
269-
}
270-
}
271-
return new AuthorizationDecision(false);
272-
}
273-
274-
}
275-
276-
private static class MethodExpressionAuthorizationManager implements AuthorizationManager<MethodInvocation> {
277-
278-
private final Expression expression;
279-
280-
private SecurityExpressionHandler<MethodInvocation> expressionHandler = new DefaultMethodSecurityExpressionHandler();
281-
282-
MethodExpressionAuthorizationManager(Expression expression) {
283-
this.expression = expression;
284-
}
285-
286-
@Override
287-
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation invocation) {
288-
EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, invocation);
289-
boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
290-
return new ExpressionAuthorizationDecision(granted, this.expression);
291-
}
292-
293-
void setExpressionHandler(SecurityExpressionHandler<MethodInvocation> expressionHandler) {
294-
this.expressionHandler = expressionHandler;
295-
}
296-
297-
}
298-
299308
}

0 commit comments

Comments
 (0)