Przeglądaj źródła

Polish InterceptMethodsBeanDefinitionDecorator

Issue gh-11328
Josh Cummings 3 lat temu
rodzic
commit
51475e2583

+ 5 - 139
config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java

@@ -16,21 +16,14 @@
 
 package org.springframework.security.config.method;
 
-import java.lang.reflect.Method;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Supplier;
 
-import org.aopalliance.intercept.MethodInvocation;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
-import org.springframework.aop.ClassFilter;
-import org.springframework.aop.MethodMatcher;
 import org.springframework.aop.Pointcut;
 import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
-import org.springframework.aop.support.AopUtils;
-import org.springframework.aop.support.RootClassFilter;
 import org.springframework.beans.BeanMetadataElement;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -41,24 +34,13 @@ import org.springframework.beans.factory.support.ManagedMap;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.Expression;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.security.access.SecurityConfig;
-import org.springframework.security.access.expression.ExpressionUtils;
-import org.springframework.security.access.expression.SecurityExpressionHandler;
-import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
 import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
-import org.springframework.security.authorization.AuthorizationDecision;
-import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
+import org.springframework.security.authorization.method.MethodExpressionAuthorizationManager;
 import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.Elements;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.access.expression.ExpressionAuthorizationDecision;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.util.xml.DomUtils;
 
@@ -93,8 +75,6 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
 
 		private static final String ATT_AUTHORIZATION_MGR = "authorization-manager-ref";
 
-		private final ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
-
 		@Override
 		protected BeanDefinition createInterceptorDefinition(Node node) {
 			Element interceptMethodsElt = (Element) node;
@@ -121,8 +101,8 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
 
 		private Pointcut pointcut(Element interceptorElt, Element protectElt) {
 			String method = protectElt.getAttribute(ATT_METHOD);
-			Class<?> javaType = javaType(interceptorElt, method);
-			return new PrefixBasedMethodMatcher(javaType, method);
+			String parentBeanClass = ((Element) interceptorElt.getParentNode()).getAttribute("class");
+			return PrefixBasedMethodMatcher.fromClass(parentBeanClass, method);
 		}
 
 		private BeanMetadataElement authorizationManager(Element interceptMethodsElt, Element protectElt) {
@@ -131,129 +111,15 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
 				return new RuntimeBeanReference(authorizationManager);
 			}
 			String access = protectElt.getAttribute(ATT_ACCESS);
-			SpelExpressionParser parser = new SpelExpressionParser();
-			Expression expression = parser.parseExpression(access);
 			return BeanDefinitionBuilder.rootBeanDefinition(MethodExpressionAuthorizationManager.class)
-					.addConstructorArgValue(expression).getBeanDefinition();
+					.addConstructorArgValue(access).getBeanDefinition();
 		}
 
 		private BeanMetadataElement authorizationManager(Map<Pointcut, BeanMetadataElement> managers) {
-			return BeanDefinitionBuilder.rootBeanDefinition(PointcutMatchingAuthorizationManager.class)
+			return BeanDefinitionBuilder.rootBeanDefinition(PointcutDelegatingAuthorizationManager.class)
 					.addConstructorArgValue(managers).getBeanDefinition();
 		}
 
-		private Class<?> javaType(Element interceptMethodsElt, String method) {
-			int lastDotIndex = method.lastIndexOf(".");
-			String parentBeanClass = ((Element) interceptMethodsElt.getParentNode()).getAttribute("class");
-			Assert.isTrue(lastDotIndex != -1 || StringUtils.hasText(parentBeanClass),
-					() -> "'" + method + "' is not a valid method name: format is FQN.methodName");
-			if (lastDotIndex == -1) {
-				return ClassUtils.resolveClassName(parentBeanClass, this.beanClassLoader);
-			}
-			String methodName = method.substring(lastDotIndex + 1);
-			Assert.hasText(methodName, () -> "Method not found for '" + method + "'");
-			String typeName = method.substring(0, lastDotIndex);
-			return ClassUtils.resolveClassName(typeName, this.beanClassLoader);
-		}
-
-		private static class PrefixBasedMethodMatcher implements MethodMatcher, Pointcut {
-
-			private final ClassFilter classFilter;
-
-			private final String methodPrefix;
-
-			PrefixBasedMethodMatcher(Class<?> javaType, String methodPrefix) {
-				this.classFilter = new RootClassFilter(javaType);
-				this.methodPrefix = methodPrefix;
-			}
-
-			@Override
-			public ClassFilter getClassFilter() {
-				return this.classFilter;
-			}
-
-			@Override
-			public MethodMatcher getMethodMatcher() {
-				return this;
-			}
-
-			@Override
-			public boolean matches(Method method, Class<?> targetClass) {
-				return matches(this.methodPrefix, method.getName());
-			}
-
-			@Override
-			public boolean isRuntime() {
-				return false;
-			}
-
-			@Override
-			public boolean matches(Method method, Class<?> targetClass, Object... args) {
-				return matches(this.methodPrefix, method.getName());
-			}
-
-			private boolean matches(String mappedName, String methodName) {
-				boolean equals = methodName.equals(mappedName);
-				return equals || prefixMatches(mappedName, methodName) || suffixMatches(mappedName, methodName);
-			}
-
-			private boolean prefixMatches(String mappedName, String methodName) {
-				return mappedName.endsWith("*")
-						&& methodName.startsWith(mappedName.substring(0, mappedName.length() - 1));
-			}
-
-			private boolean suffixMatches(String mappedName, String methodName) {
-				return mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1));
-			}
-
-		}
-
-		private static class PointcutMatchingAuthorizationManager implements AuthorizationManager<MethodInvocation> {
-
-			private final Map<Pointcut, AuthorizationManager<MethodInvocation>> managers;
-
-			PointcutMatchingAuthorizationManager(Map<Pointcut, AuthorizationManager<MethodInvocation>> managers) {
-				this.managers = managers;
-			}
-
-			@Override
-			public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation object) {
-				for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
-					Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis())
-							: null;
-					if (entry.getKey().getClassFilter().matches(targetClass)
-							&& entry.getKey().getMethodMatcher().matches(object.getMethod(), targetClass)) {
-						return entry.getValue().check(authentication, object);
-					}
-				}
-				return new AuthorizationDecision(false);
-			}
-
-		}
-
-		private static class MethodExpressionAuthorizationManager implements AuthorizationManager<MethodInvocation> {
-
-			private final Expression expression;
-
-			private SecurityExpressionHandler<MethodInvocation> expressionHandler = new DefaultMethodSecurityExpressionHandler();
-
-			MethodExpressionAuthorizationManager(Expression expression) {
-				this.expression = expression;
-			}
-
-			@Override
-			public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation invocation) {
-				EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, invocation);
-				boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
-				return new ExpressionAuthorizationDecision(granted, this.expression);
-			}
-
-			void setExpressionHandler(SecurityExpressionHandler<MethodInvocation> expressionHandler) {
-				this.expressionHandler = expressionHandler;
-			}
-
-		}
-
 	}
 
 	/**

+ 50 - 0
config/src/main/java/org/springframework/security/config/method/PointcutDelegatingAuthorizationManager.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2022 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.security.config.method;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.core.Authentication;
+
+class PointcutDelegatingAuthorizationManager implements AuthorizationManager<MethodInvocation> {
+
+	private final Map<Pointcut, AuthorizationManager<MethodInvocation>> managers;
+
+	PointcutDelegatingAuthorizationManager(Map<Pointcut, AuthorizationManager<MethodInvocation>> managers) {
+		this.managers = managers;
+	}
+
+	@Override
+	public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation object) {
+		for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
+			Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
+			if (entry.getKey().getClassFilter().matches(targetClass)
+					&& entry.getKey().getMethodMatcher().matches(object.getMethod(), targetClass)) {
+				return entry.getValue().check(authentication, object);
+			}
+		}
+		return new AuthorizationDecision(false);
+	}
+
+}

+ 95 - 0
config/src/main/java/org/springframework/security/config/method/PrefixBasedMethodMatcher.java

@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2022 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.security.config.method;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.support.RootClassFilter;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.StringUtils;
+
+class PrefixBasedMethodMatcher implements MethodMatcher, Pointcut {
+
+	private static final ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
+
+	private final ClassFilter classFilter;
+
+	private final String methodPrefix;
+
+	PrefixBasedMethodMatcher(Class<?> javaType, String methodPrefix) {
+		this.classFilter = new RootClassFilter(javaType);
+		this.methodPrefix = methodPrefix;
+	}
+
+	static PrefixBasedMethodMatcher fromClass(String className, String method) {
+		int lastDotIndex = method.lastIndexOf(".");
+		Assert.isTrue(lastDotIndex != -1 || StringUtils.hasText(className),
+				() -> "'" + method + "' is not a valid method name: format is FQN.methodName");
+		if (lastDotIndex == -1) {
+			Class<?> javaType = ClassUtils.resolveClassName(className, beanClassLoader);
+			return new PrefixBasedMethodMatcher(javaType, method);
+		}
+		String methodName = method.substring(lastDotIndex + 1);
+		Assert.hasText(methodName, () -> "Method not found for '" + method + "'");
+		String typeName = method.substring(0, lastDotIndex);
+		Class<?> javaType = ClassUtils.resolveClassName(typeName, beanClassLoader);
+		return new PrefixBasedMethodMatcher(javaType, method);
+	}
+
+	@Override
+	public ClassFilter getClassFilter() {
+		return this.classFilter;
+	}
+
+	@Override
+	public MethodMatcher getMethodMatcher() {
+		return this;
+	}
+
+	@Override
+	public boolean matches(Method method, Class<?> targetClass) {
+		return matches(this.methodPrefix, method.getName());
+	}
+
+	@Override
+	public boolean isRuntime() {
+		return false;
+	}
+
+	@Override
+	public boolean matches(Method method, Class<?> targetClass, Object... args) {
+		return matches(this.methodPrefix, method.getName());
+	}
+
+	private boolean matches(String mappedName, String methodName) {
+		boolean equals = methodName.equals(mappedName);
+		return equals || prefixMatches(mappedName, methodName) || suffixMatches(mappedName, methodName);
+	}
+
+	private boolean prefixMatches(String mappedName, String methodName) {
+		return mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1));
+	}
+
+	private boolean suffixMatches(String mappedName, String methodName) {
+		return mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1));
+	}
+
+}

+ 21 - 0
core/src/main/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManager.java

@@ -0,0 +1,21 @@
+/*
+ * Copyright 2002-2022 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.security.authorization.method;
+
+public class MethodExpressionAuthorizationManager {
+
+}